开发者

Can I use SetErrorMode in C# process?

I'm preparing for writing an online judge core,

A program that can compile user's code and run the program to check the answer like uva online judge.

And I'm having problem in catching the exception of submit program like below.

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

it's access denied at first line because it scan an integer to error position.

how can I catch runtime error for my process?

I used to use "try catch" to catch the exception,

but it didn't reply anything about runtime error.

so I only check the exit code of the submit program although it's not a good method to check except for a process..

and it shows like photo

I have to close the error message box manually,

and I find a solution that is to use a SEH Handler DLL for the process.

SetErrorMode(SEM_NOGPFAULTERRORBOX);

but I don't know how to use it in C# process.

and below is my code of judger

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;

Thanks for helping, and so sorry for my poor English.

==============================开发者_高级运维====

p.s.

the question is how can I set error mode for the child process in C#.

My English is not good enough to explain the problem, so sorry.<(_ _)>


If you mean the Win32 API function SetErrorMode then you'll need to use P/Invoke, which is easy with such a simple signature:

[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
}

(The Site http://www.pinvoike.net/ is always a good place to start to get the right declaration.)


You cannot set the error mode in another process without injecting code into that process. Which is impossible to do easily in C#. It isn't going to work well in C/C++ either, these kind of programs don't live long enough to give you time to inject.

It doesn't solve your problem anyway, you also have to protect against programs that never exit after they got stuck in an endless loop. The simple solution is to give every program a limited amount of time to execute. Say 10 seconds. If it doesn't complete then Process.Kill() it and declare a failure. This will also take care of the programs that bomb with a message box.

Trivial to implement with the Process.WaitForExit(milliseconds) overload.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜