2012-05-19 356 views
2

我有一個使用AciveX對象並提供WCF服務的C#WPF程序。所以有很多線程,很多調用非託管代碼。有時在滿載的應用程序崩潰。我正在調查這個問題 - 它看起來像是ActiveX中的某個地方出現問題,我無法改變。無論如何,我需要一種方式來在崩潰後恢復程序。至於現在我已經找到了解決方案:如何防止顯示「程序意外終止」窗口?

public partial class App : Application 
{ 
    private static readonly Logger log = LogManager.GetCurrentClassLogger(); 

    bool isClosing = false; 


    [System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute] 
    void D_UnhandledException(object sender, UnhandledExceptionEventArgs e) 
    { 
     log.FatalException("Error UnhandledException ", (Exception)e.ExceptionObject); 
     MonitoringSvc.host.Close(); 
     log.Info("Restarting"); 
     if (!isClosing) 
     { 

      System.Windows.Forms.Application.Restart(); 
      System.Windows.Application.Current.Shutdown(); 
     } 
    } 


    private void Application_Startup(object sender, StartupEventArgs e) 
    { 
     AppDomain D = AppDomain.CurrentDomain; 
     D.UnhandledException += new UnhandledExceptionEventHandler(D_UnhandledException); 
    } 

    private void Application_Exit(object sender, ExitEventArgs e) 
    { 
     isClosing = true; 
    } 
} 

程序重新啓動未處理的異常(模擬肯定)。但是,舊的副本保持未關閉系統消息「程序意外終止」。程序不會在大多數時間與用戶交互,因此沒有人可以關閉該消息來關閉程序。問題是如何默默關閉舊窗戶?

+0

也許試試,趕,殺? – t3hn00b

+0

該屬性不夠,還需要[SecurityCritical]。或者使用app.exe.config文件中的''元素。仍然無法保證,CLR無法捕捉由本機代碼啓動的線程中的硬異常。您需要爲流程禁用WER。詢問superuser.com。這種類型的芭比是一個糟糕的兔子洞。 –

+0

也許最好寫一個簡單的監護人程序。當它停止響應某些看門狗消息時,它可以終止主進程。還可以在意外退出時重新啓動。我不確定WER是否適用於兒童進程? – xdenser

回答

5

這裏是解決方案如何禁用窗口出現在程序崩潰。不僅WER,因爲即使WER禁用,其他窗口也會顯示(要求關閉或調試程序)。

[DllImport("kernel32.dll", SetLastError = true)] 
    static extern int SetErrorMode(int wMode); 

    [DllImport("kernel32.dll")] 
    static extern FilterDelegate SetUnhandledExceptionFilter(FilterDelegate lpTopLevelExceptionFilter); 
    public delegate bool FilterDelegate(Exception ex); 

    App() 
    { 
     FilterDelegate fd = delegate(Exception ex) 
     { 
      return true; 
     }; 
     SetUnhandledExceptionFilter(fd); 

     SetErrorMode(SetErrorMode(0) | 0x0002); 
    } 
+0

哦,我剛剛發現了一件有趣的事情:事實上,傳遞給SetUnhandledExceptionFilter的委託不會被調用。我認爲這是因爲SetUnhandledExceptionFilter需要一個指向本地函數的指針,而不是.NET委託。我們可以通過那裏(IntPtr)0,效果將是相同的:異常將被默默地忽略。但是如果我們想用真正的託管函數來處理異常,我們應該把它放到Dll中,然後檢索它的地址,然後把它提交給SetUnhandledExceptionFilter。我還沒有嘗試過。 –