我可以在C#进程中使用SetErrorMode吗?

时间:2011-05-21 08:37:53

标签: c# winapi

我正准备写一个在线评判核心,
一个程序,可以编译用户的代码并运行程序来检查答案,如uva在线评判。

我在捕获提交程序的例外方面遇到了问题,如下所示。

int main()
{
    while(~scanf("%d %d",n,&m))
    {   
        printf("%d\n",n+m);
    }
    return 0;
}

它在第一行被拒绝,因为它将整数扫描到错误位置 如何捕获我的进程的运行时错误?

我曾经使用“try catch”来捕捉异常,
但它没有回复有关运行时错误的任何内容。

所以我只检查提交程序的退出代码,虽然它不是一个好的方法来检查除了进程..
它显示为photo

我必须手动关闭错误信息框,
我找到了一个解决方案,即使用SEH Handler DLL进行处理。

SetErrorMode(SEM_NOGPFAULTERRORBOX);

但我不知道如何在C#进程中使用它。

以下是我的判断代码

timer = new Stopwatch();
timer.Reset();

submitProg = new Process();
submitProg.StartInfo.FileName = outputFile;
submitProg.StartInfo.UseShellExecute = false;
submitProg.StartInfo.CreateNoWindow = true;
submitProg.StartInfo.RedirectStandardInput = true;
submitProg.StartInfo.RedirectStandardOutput = true;
submitProg.StartInfo.RedirectStandardError = true;
submitProg.StartInfo.ErrorDialog = false;
submitProg.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
submitProg.EnableRaisingEvents = true;

submitProg.Start();
timer.Start();

progInput = submitProg.StandardInput;
progOutput = submitProg.StandardOutput;

progInput.Write(inputStream.ReadToEnd());
submitProg.StandardInput.Close();
while (!submitProg.HasExited)
{
    peakPagedMem = submitProg.PeakPagedMemorySize64;
    peakVirtualMem = submitProg.PeakVirtualMemorySize64;
    peakWorkingSet = submitProg.PeakWorkingSet64;
    if (peakPagedMem > memLimit)
    {
        submitProg.Kill();
    }
    if (timer.ElapsedMilliseconds > timeLimit)
    {
        timeLimitExceed = true;
        submitProg.Kill();
    }
}

timeUsed = timer.ElapsedMilliseconds;
timer.Stop();

if(submitProg.ExitCode!=0)systemRuntimeError = true;

感谢您的帮助,也很抱歉我的英语不好。

==================================
附:
问题是如何在C#中为子进程设置错误模式 我的英语不足以解释这个问题,很抱歉。<(_ _)>

2 个答案:

答案 0 :(得分:10)

如果您的意思是Win32 API函数SetErrorMode,那么您需要使用P/Invoke,这样的简单签名很容易:

[DllImport("kernel32.dll")]
static extern ErrorModes  SetErrorMode(ErrorModes uMode);

[Flags]
public enum ErrorModes : uint {
    SYSTEM_DEFAULT             = 0x0,
    SEM_FAILCRITICALERRORS     = 0x0001,
    SEM_NOALIGNMENTFAULTEXCEPT = 0x0004,
    SEM_NOGPFAULTERRORBOX      = 0x0002,
    SEM_NOOPENFILEERRORBOX     = 0x8000
}

(网站http://www.pinvoike.net/始终是开始获得正确声明的好地方。)

答案 1 :(得分:5)

如果不将代码注入该进程,则无法在另一个进程中设置错误模式。在C#中不可能轻松做到这一点。它在C / C ++中也不会很好用,这些程序的活动时间不够长,无法给你时间注入。

无论如何它都无法解决您的问题,您还必须防止它们在无限循环中陷入困境后永不退出的程序。简单的解决方案是为每个程序提供有限的执行时间。说10秒。如果它没有完成,那么Process.Kill()它并声明失败。这也将照顾用消息框炸弹的程序。

使用Process.WaitForExit(毫秒)重载实现的过程非常简单。