2011-05-21 60 views
6

我準備寫在線評委核心,
一個程序,可以編譯用戶的代碼,並運行程序來檢查答案,如uva在線裁判。我可以在C#過程中使用SetErrorMode嗎?

而我在抓取下面提交程序的例外時遇到問題。

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; 

感謝您的幫助,爲我的英語很差很抱歉。

==================================
p.s.
問題是如何在C#中爲子進程設置錯誤模式。
我的英語不夠好解釋問題,所以很抱歉。 <(_ _)>

+0

有幾個錯誤框不應該是一個問題,因爲你需要在任何情況下沙箱你的事情很好。你可以用它殺死沙箱和進程。 – 2011-05-21 08:59:33

回答

5

您不能在另一個進程中設置錯誤模式,而無需在該進程中注入代碼。在C#中不可能做到這一點。它在C/C++中也不能很好地工作,這些程序的壽命不夠長,無法給你時間注入。

無論如何它並不能解決您的問題,您還必須防止程序在被無限循環卡住後永遠不會退出。簡單的解決方案是爲每個程序提供有限的執行時間。說10秒。如果它沒有完成,那麼Process.Kill()它並聲明失敗。這也將照顧用消息框炸彈的程序。

使用Process.WaitForExit(毫秒)過載實現微不足道。

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/始終是一個好開始獲得正確的聲明。)

+0

它是否也適用於子進程? – Nekosyndrome 2011-05-21 09:41:34

+0

@kannaduki在MSDN上沒有提到它是由子進程繼承的 - 因此我會認爲它是* not * inherited。 – Richard 2011-05-21 09:54:15

+0

它似乎不被繼承。我怎樣才能爲我的子進程@@設置錯誤模式?謝謝。 – Nekosyndrome 2011-05-21 10:20:14

相關問題