【问题标题】:Can I use SetErrorMode in C# process?我可以在 C# 进程中使用 SetErrorMode 吗?
【发布时间】:2011-05-21 19:11:19
【问题描述】:

我正在准备写一个在线法官核心,
一个可以编译用户代码并运行程序来检查答案的程序,就像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# 中为子进程设置错误模式。
我的英语不够好,无法解释问题,非常抱歉。

【问题讨论】:

  • 有几个错误框应该不是问题,因为无论如何你都需要很好地沙箱化你的东西。你可以杀死沙箱和它的进程。

标签: c# winapi


【解决方案1】:

如果您指的是 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/ 始终是开始获得正确声明的好地方。)

【讨论】:

  • @kannaduki MSDN 上没有提到这是由子进程继承的——因此我希望它不是继承的。
  • 好像不是继承的。如何为我的子进程@@ 设置错误模式?谢谢。
  • @kannaduki 设置它。我从 MSDN 中注意到在 Win7/2008R2 中使用 SetThreadErrorMode 的建议——它是一个新的 API——因为它“破坏性较小”。 IE。只有在编写和测试 exe 及其使用的库时考虑到不同的错误模式,这样更改全局状态才是安全的。
【解决方案2】:

您不能在另一个进程中设置错误模式,除非将代码注入该进程。这在 C# 中是不可能轻易做到的。它在 C/C++ 中也不能很好地工作,这类程序的寿命不够长,无法给你注入的时间。

无论如何,它并不能解决您的问题,您还必须防止程序在陷入无限循环后永远不会退出。简单的解决方案是给每个程序有限的执行时间。说 10 秒。如果它没有完成,那么 Process.Kill() 它并声明失败。这也将处理带有消息框的程序。

使用 Process.WaitForExit(milliseconds) 重载实现起来很简单。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-06
    • 2016-08-31
    • 2012-07-09
    • 2012-07-02
    相关资源
    最近更新 更多