簡體   English   中英

如何在Windows服務中設置.NET UnhandledException處理?

[英]How can I set up .NET UnhandledException handling in a Windows service?

protected override void OnStart(string[] args)
{
    AppDomain.CurrentDomain.UnhandledException +=
        new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    Thread.Sleep(10000);

    throw new Exception();
}

void CurrentDomain_UnhandledException(object sender,
                                      UnhandledExceptionEventArgs e)
{
}

我在我的Windows服務中將調試器附加到上面的代碼,在CurrentDomain_UnhandledException中設置斷點,但它從未被命中。 彈出的異常是說它未處理,然后服務停止。 我甚至嘗試在事件處理程序中放入一些代碼,以防它被優化掉。

這不是在Windows服務中設置未處理的異常處理的正確方法嗎?

當前AppDomain上的UnhandledException事件未觸發的原因是服務的執行方式。

  1. 用戶從Windows服務控制管理器(SCM)發送“啟動”命令。
  2. 該命令由框架的ServiceBase實現接收,並分派給OnStart方法。
  3. 調用OnStart方法。

OnStart拋出的任何異常都在基類中處理 ,記錄到事件日志中,並轉換為返回給SCM的錯誤狀態代碼。 因此,異常永遠不會傳播到AppDomain的未處理異常處理程序。

我認為您會發現從您的服務中的工作線程拋出的未處理異常被AppDomain的未處理異常處理程序捕獲。

在Windows服務中,您不希望在OnStart方法中運行太多代碼。 您只需要啟動服務線程然后返回的代碼。

如果這樣做,您可以處理服務線程中發生的異常。

例如

public static void Start()
{
    AppDomain currentDomain = AppDomain.CurrentDomain;
    currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);

    running = true;
    ThreadStart ts = new ThreadStart(ServiceThreadBody);
    thread = new Thread(ts);
    thread.Name = "ServiceThread";
    thread.Priority = ThreadPriority.BelowNormal;
    thread.Start();
}

知道這個線程有點舊,但認為根據在.NET中開發Windows服務的個人經驗添加一些注釋會很有用。 最好的方法是盡可能避免在服務控制管理器下進行開發 - 為此你需要一個模擬服務啟動方式的簡單工具 - 可以創建服務類實例的東西(你已經從ServiceBase派生的) )並調用您的OnStart,OnStop等方法。 根據需要,此線束可以是控制台應用程序或Windows應用程序。

這幾乎是我在.NET中調試服務啟動問題的唯一方法 - 您的代碼,Visual Studio和真正的服務控制管理器之間的交互只會使該過程無法實現。

HTH。

當我在自己的Windows服務上工作時,它已經奇怪地停止了。 我以為是因為無恥的例外。 目前我正在文本文件中捕獲無法處理的異常。 首先,由於在文本文件上記錄了excaptions,您必須在C位置創建新文件ServiceLog.txt。 在下面的編碼中,我得到了所有未加掩蓋的例外情況。

using System.Security.Permissions;
using System.IO;

[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
    protected override void OnStart(string[] args)
    {   AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
        ...
        Your codes...
        ....
    }
    void MyHandler(object sender, UnhandledExceptionEventArgs args)
    {
        Exception e = (Exception)args.ExceptionObject;
        WriteToFile("Simple Service Error on: {0} " + e.Message + e.StackTrace);
    }
    private void WriteToFile(string text)
    {
        string path = "C:\\ServiceLog.txt";
        using (StreamWriter writer = new StreamWriter(path, true))
        {
            writer.WriteLine(string.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")));
            writer.Close();
        }
    }

只是好奇,你想要完成什么:避免服務崩潰,或報告錯誤?

對於報告,我認為最好的辦法是添加頂級的try / catch語句。 您可以嘗試將它們記錄到Windows事件日志和/或日志文件中。

您還可以將ExitCode屬性設置為非零值,直到您成功停止服務。 如果系統管理員從“服務”控制面板啟動服務,並且您的服務突然停止並使用非零退出代碼,則Windows可以顯示包含錯誤描述的錯誤消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM