如何在Windows服务中设置.NET UnhandledException处理?

时间:2010-03-16 17:54:53

标签: c# windows-services exception-handling unhandled-exception

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服务中设置未处理的异常处理的正确方法吗?

4 个答案:

答案 0 :(得分:53)

当前AppDomain上的UnhandledException事件未触发的原因是服务的执行方式。

  1. 用户从Windows服务控制管理器(SCM)发送启动命令。
  2. 该命令由框架的ServiceBase实现接收,并发送到OnStart方法。
  3. 调用OnStart方法。
  4. OnStart引发的任何异常都在基类中处理,记录到事件日志中,并转换为返回给SCM的错误状态代码。因此,异常永远不会传播到AppDomain的未处理异常处理程序。

    我认为您会发现从服务中的工作线程抛出的未处理异常将被AppDomain的未处理异常处理程序捕获。

答案 1 :(得分:9)

在Windows服务中,您不希望在OnStart方法中运行太多代码。您只需要启动服务线程然后返回的代码。

如果这样做,您可以处理服务线程中发生的异常。

e.g。

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();
}

答案 2 :(得分:4)

知道这个线程有点旧,但认为根据在.NET中开发Windows服务的个人经验添加一些注释会很有用。 最好的方法是尽可能避免在服务控制管理器下进行开发 - 为此,您需要一个模仿服务启动方式的简单工具 - 这可以是创建服务类的实例(您已从ServiceBase派生)并调用OnStart,OnStop等方法。根据需要,此线束可以是控制台应用程序或Windows应用程序。

这几乎是我在.NET中调试服务启动问题的唯一方法 - 您的代码,Visual Studio和真正的服务控制管理器之间的交互只会使该过程无法实现。

HTH。

答案 3 :(得分:2)

好奇,你想要完成什么:避免服务崩溃或报告错误?

对于报告,我认为最好的办法是添加顶级的try / catch语句。您可以尝试将它们记录到Windows事件日志和/或日志文件中。

在成功停止服务之前,您还可以将ExitCode属性设置为非零值。如果系统管理员从“服务”控制面板启动您的服务,并且您的服务突然停止并使用非零退出代码,则Windows可以显示错误消息以及错误描述。