• 由成幻OnlineJudge学习如何做自己的AcmIcpc在线评判系统-5.在线编译与测试系统代码粗解


    由于近来很忙,加之此类文章少有人问津.所以少有时间写这一系列的文章的续篇
    所以先把核心在线编译的代码发出来,细的部分大家可以查资料,或者留言问我^^
    部分类库可以查我以前的文章
    using System;
    using System.Text;
    using System.Data;
    using System.Diagnostics;
    using System.Threading;
    using System.IO;

    namespace ChswordOJ {
        
    /// <summary>
        
    /// DoFile 进行在线编译与测试
        
    /// Builder:邹健 2007 4 28
        
    /// V1.0 2007 6 12
        
    /// </summary>
        public class DoFile {
            StringBuilder _output 
    = new StringBuilder();
            StringBuilder _TestOutput 
    = new StringBuilder();
            StringBuilder _TestFile_Output 
    = new StringBuilder();
            String _Test;
            String _CompilerName;
            StringBuilder _CompilerText 
    = new StringBuilder();
            
    private Int64 _Memory, _myMemory;
            
    private Int32 _Time;//, _myTime;
            private Option.AnswerStatus _TestResult;
            
    private String _ExePath;
            
    private String _CodePath;
            
    private String _TextPath;
            
    private String _TestPath;
            
    private Int64 _AnswerId;
            
    private String _Sign;
            
    private Boolean _TestEnd;
            Process _process;
            
    /// <summary>
            
    /// 构造函数,对DoFile类进行初始化
            
    /// </summary>
            public DoFile() {
                _Memory 
    = 23768;
                _Time 
    = 3;
            }
            
    /// <summary>
            
    /// 进行编译及测试代码。
            
    /// </summary>
            
    /// <param name="code">要编译的代码。</param>
            
    /// <param name="UserName">编译的用户名。</param>
            
    /// <param name="PassWord">用户密码。</param>
            
    /// <param name="QNum">代码的问题ID。</param>
            
    /// <param name="CompilerName">编译器。</param>
            public void GetResult(String code, String UserName, String PassWord, String QNum, String CompilerName) {
                Option cp 
    = new Option();
                DataSet ds 
    = cp.GetLimit(QNum);
                User u 
    = new User(UserName, CompilerName.Split(',')[0], CompilerName.Split(',')[1]);
                _Memory 
    = int.Parse(ds.Tables[0].Rows[0][0].ToString());//从数据库读取当前的程序 要求的Memory
                _Time = int.Parse(ds.Tables[0].Rows[0][1].ToString());//从数据库读取当前的程序 要求的Time limit
                _Test = ds.Tables[0].Rows[0]["test"].ToString();//读取测试文件
                _CompilerName = CompilerName;//编译器名称
                _Sign = u.Sign;
                _CodePath 
    = u.CodePath;//源代码文件保存的路径
                _TextPath = u.TextPath;//生成文本文件保存的路径
                _ExePath = u.ExePath;//EXE文件保存的路径
                _myMemory = 0;//对我当前耗费的内存进行初始化
                _TestPath = u.GetTestPath(QNum);//得到当前测试路径
                _AnswerId = cp.AddAnswer(UserName, Int64.Parse(QNum), CompilerName);//将当前数据作为一条回答存入数据库(创建一条数据库记录)
                Code cc = new Code(CompilerName, code);//创建Code实例
                if (cc.Check()) {//调用配置文件中的正则表达式,测试代码中有无危险代码,有,则此回答为危险代码

                    SaveTextFile(u.CodePath, code);
    //将源代码保存为相应格式文件
                    _CompilerText.AppendLine(u.CompilerString);//
                    DoCmd(u.CompilerString);//用u生成编译字符串,执行编译操作
                    IsTempExists(u.TextPath, u.CompilerString);//是否编译完成
                    if (0 == _AnswerId)
                        
    return;
                    cp.SetAnswerStatus(_AnswerId, Option.AnswerStatus.编译中);
                    
    //编译完成
                    if (IsCompilerSucess(u.TextPath, u.CodePath, u.ExePath, 0)) {//编译产生EXE则编译成功
                        
    //编译成功
                        cp.SetAnswerStatus(_AnswerId, Option.AnswerStatus.测试中);
                        ThreadStart thr_start_func 
    = new ThreadStart(Test);//异步调用Test进行测试
                        Thread fThread = new Thread(thr_start_func);
                        fThread.Name 
    = "Test";
                        fThread.Start();
                        Thread.Sleep(_Time 
    * 2000);//初始化最大超时时间(规定时间的2倍)
                        if (Option.AnswerStatus.测试通过 == _TestResult) {
                            
    //cp.SetAnswerStatus(_AnswerId, Compiler.AnswerStatus.测试通过);
                        }
                        
    else {
                            
    if (_TestResult == 0) {
                                
    try {
                                
    //对进程查看是否结束,未结束则进行操作
                                    if (!_process.HasExited) {
                                        
    if (!_process.CloseMainWindow())
                                            _process.Kill();
                                        
    if (_TestFile_Output.ToString().StartsWith(_TestOutput.ToString()))
                                            _TestResult 
    = Option.AnswerStatus.超时;
                                        
    else
                                            _TestResult 
    = Option.AnswerStatus.测试失败;
                                    }
                                }
                                
    catch {
                                    _TestResult 
    = Option.AnswerStatus.测试失败;
                                }

                            }
                            
    if (fThread.IsAlive) fThread.Abort();//最终的强制结束进程
                        }
                    }
                    
    else {
                        _TestResult 
    = Option.AnswerStatus.编译失败;
                        cp.SetAnswerText(_AnswerId, ReplaceFileName(_CompilerText.ToString()));
                    }

                    
    try {
                        
    if (_TestResult == Option.AnswerStatus.测试中 || _TestResult == Option.AnswerStatus.测试失败) {
                            Process[] p 
    = Process.GetProcessesByName(_Sign);
                            
    if (p.Length > 0) {
                                
    if (!p[0].HasExited) {
                                    
    if (p[0].Responding) {
                                        p[
    0].CloseMainWindow();
                                        p[
    0].Kill();
                                    }
                                    
    else {
                                        p[
    0].Kill();
                                    }
                                }
                                
    if (_TestFile_Output.ToString().StartsWith(_TestOutput.ToString()))
                                    _TestResult 
    = Option.AnswerStatus.超时;
                                
    else
                                    _TestResult 
    = Option.AnswerStatus.测试失败;
                            }
                        }
                    }
                    
    catch { }
                }
                
    else {
                    _TestResult 
    = Option.AnswerStatus.危险代码;
                }

                cp.SetAnswerStatus(_AnswerId, _TestResult);
    //写入测试结果
                cp.SaveAnswerCode(_AnswerId, code);//写入提交的源代码
                /*try {
                    if (_TestResult == Option.AnswerStatus.测试通过) {
                        using (StreamReader sr = File.OpenText(_CodePath)) {
                            cp.SaveAnswerCode(_AnswerId, sr.ReadToEnd());
                        }
                    }
                }
                catch { }
    */
                DeleteTempFile();
    //删除临时文件
            }

            
    private void DeleteTempFile() {//删除临时文件
                Byte b = 0;
                
    try {
                    Thread.Sleep(
    1000);//每一秒试删除一次
                    if (File.Exists(_ExePath)) File.Delete(_ExePath); else b++;
                    
    if (File.Exists(_CodePath)) File.Delete(_CodePath); else b++;
                    
    if (File.Exists(_TextPath)) File.Delete(_TextPath); else b++;
                }
                
    catch { }
                
    if (b != 3) DeleteTempFile();//递归调用
                return;
            }
            
    private bool IsCompilerSucess(string TextPath, string CppPath, String ExePath, int count) {
                
    try {//看是否编译成功的函数
                    using (StreamReader sr = new StreamReader(TextPath, Encoding.Default)) {
                        String input;
                        
    bool f = true;
                        
    while ((input = sr.ReadLine()) != null) {
                            _CompilerText.AppendLine(input);
                            
    if (input.Contains(": error:")) {

                                _output.AppendLine(input);
                            }
                            
    else {
                                
    if (f && !input.StartsWith(CppPath))
                                    _output.AppendLine(input);
                                f 
    = false;
                            }
                        }
                        sr.Close();
                        
    if (File.Exists(ExePath)) {
                            
    return true;
                        }
                        
    else {
                            _output.Insert(
    0"编译出错:\r\n");
                            
    return false;
                        }
                    }
                }
                
    catch {
                }
                Thread.Sleep(
    1000);
                
    if (count >= 300) {
                    _CompilerText.Insert(
    0"服务器响应超时或您选择的编译器不正确");
                    
    return false;
                }
                
    return IsCompilerSucess(TextPath, CppPath, ExePath, count + 1);
            }
            
    private string ReplaceFileName(string input) {
                input 
    = System.Text.RegularExpressions.Regex.Replace(input, @"([A-Z]:[\\|\/][^:\*\?<>\|]+\.(txt|cs|cpp|c|vb|jsl|js|exe))|(\\{2}[^/:\*\?<>\|]+\.(txt|cs|cpp|c|vb|jsl|js|exe))"">", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                
    return input;
            }
            
    private void Process_Exited(object sender, EventArgs e) {//测试程序是否超时的判断
                if (_process.TotalProcessorTime.Milliseconds > _Time*1000) {
                    
    if (_TestFile_Output.ToString().StartsWith(_TestOutput.ToString()))
                        _TestResult 
    = Option.AnswerStatus.超时;
                    
    else
                        _TestResult 
    = Option.AnswerStatus.测试失败;
                }
            }
            
    private void Test() {//进行测试
                string ExePath = _ExePath;
                
    string TestPath = _TestPath;
                String input;
                
    bool f = true;
                _TestEnd 
    = false;
                _process 
    = new Process();
                _process.StartInfo.WindowStyle 
    = ProcessWindowStyle.Hidden;
                _process.StartInfo.UseShellExecute 
    = false;
                _process.StartInfo.CreateNoWindow 
    = true;
                _process.StartInfo.RedirectStandardInput 
    = true;
                _process.StartInfo.RedirectStandardOutput 
    = true;
                _process.StartInfo.RedirectStandardError 
    = true;
                _process.StartInfo.FileName 
    = ExePath;
                _process.Exited 
    += new EventHandler(Process_Exited);
                _process.OutputDataReceived 
    += new DataReceivedEventHandler(TestOutputHandler);
                _process.Start();
                _process.BeginOutputReadLine();
                _myMemory 
    = (_process.PeakWorkingSet64 >> 10);//获取内存大小
                StreamWriter sortStreamWriter = _process.StandardInput;//设置异步读取流
                try {
                    
    using (StringReader sr = new StringReader(_Test)) {
                        
    while (((input = sr.ReadLine()) != null)) {
                            
    if (input.StartsWith("EOF"))//C/C++程序的结束(CTRL+Z)方式
                                if (_CompilerName.ToLower() == "c" || _CompilerName.ToLower() == "cpp")
                                    sortStreamWriter.WriteLine(((
    char)26).ToString());
                                
    else//.net程序的结束(CTRL+Z)方式
                                    _process.CloseMainWindow();
                            
    if (input.StartsWith(">"))//测试的写操作
                                sortStreamWriter.WriteLine(input.Substring(1));
                            
    if (input.StartsWith("<"))//测试的读操作
                                _TestFile_Output.AppendLine(input.Substring(1));
                        }
                    }
                    sortStreamWriter.Close();
                    _process.WaitForExit();
                    _TestEnd 
    = true;
                }
                
    catch {
                    _TestEnd 
    = true;
                }

                
    if (_TestOutput.ToString() == _TestFile_Output.ToString())
                    f 
    = true;
                
    else
                    f 
    = false;
                
    if (_TestEnd && f)
                    _TestResult 
    = Option.AnswerStatus.测试通过;
                
    else {

                }
                
    if (_TestEnd && (_myMemory > _Memory))//内存消耗太大
                {
                    _TestResult 
    = Option.AnswerStatus.内存超量;
                }
                _process.Close();
                _process.Dispose();
                
    if (f && _TestEnd) {
                    _TestResult 
    = Option.AnswerStatus.测试通过;
                }
                
    return;

            }
            
    void SaveTextFile(string Path, string text) {
                
    using (StreamWriter sw = new StreamWriter(Path)) { sw.Write(text); }
            }
            
    void DoCmd(string cmd) {//执行一条CMD命令的函数
                Process process = new Process();
                process.StartInfo.WindowStyle 
    = ProcessWindowStyle.Hidden;
                process.StartInfo.UseShellExecute 
    = false;
                process.StartInfo.CreateNoWindow 
    = true;
                process.StartInfo.RedirectStandardInput 
    = true;
                process.StartInfo.RedirectStandardError 
    = true;
                process.StartInfo.FileName 
    = "cmd.exe";
                process.Start();
                process.StandardInput.WriteLine(cmd);
                process.StandardInput.WriteLine(
    "\r\nexit");
                process.Close();
                process.Dispose();
            }
            
    bool IsTempExists(String TextPath, String CompilerString) {
                
    int i = 0;
                
    while (!File.Exists(TextPath)) {
                    Thread.Sleep(
    1000);
                    i
    ++;
                    
    if (i > 178return false;
                    
    if (i % 30 == 0 && i > 10) {
                        DoCmd(CompilerString);
                    }
                }
                
    return true;
            }
            
    private void TestOutputHandler(object sendingProcess,
                DataReceivedEventArgs outLine) {
                
    int numOutputLines = 0;
                
    if (!String.IsNullOrEmpty(outLine.Data)) {
                    numOutputLines
    ++;
                    
    //Environment.NewLine +"[" + numOutputLines.ToString() + "] - " + 
                    _TestOutput.AppendLine(outLine.Data);
                }
            }
        }

    }

    上篇:由成幻OnlineJudge学习如何做自己的Acm-Icpc在线评判系统-4.建立基本的网站类库
  • 相关阅读:
    AngularJS 最常用的八种功能
    angularJs自定义模块
    angularJs 购物车模型
    angularJs-未加载完成的页面显示混乱ng-bind
    angularJs-脏检查
    angularJs-控制器
    【转载更新】Linux工具之SED 2.应用实例
    【转载更新】Linux工具之SED 1.基础知识
    【转载更新】Linux工具之AWK 4.实例
    【转载更新】Linux工具之AWK 3.高级知识
  • 原文地址:https://www.cnblogs.com/chsword/p/875865.html
Copyright © 2020-2023  润新知