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服务中设置未处理的异常处理的正确方法吗?
答案 0 :(得分:53)
当前AppDomain上的UnhandledException
事件未触发的原因是服务的执行方式。
ServiceBase
实现接收,并发送到OnStart
方法。OnStart
方法。 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可以显示错误消息以及错误描述。