42
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服务中设置.NET UnhandledException处理?

这不是在Windows服务中设置未处理的异常处理的正确方法吗?

回答

2

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

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

您还可以将ExitCode属性设置为非零值,直到您成功停止该服务。如果系统管理员从“服务”控制面板启动服务,并且服务突然停止并显示非零退出代码,则Windows可以显示错误消息和错误说明。

+0

调试。我尝试了解所有的例外情况,但其中一个以某种方式逃避我。我认为这将是一个更易于管理的解决方案。 – 2010-03-16 18:53:58

+0

OnStart或OnStop中发生异常吗?你有关于异常的其他信息吗? – 2010-03-22 13:34:03

9

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

我最近有一个地方,因为我的服务仍然运行,但没有任何过程...我开始认为这可能是由于“吞食”异常。想知道你对我的问题有什么想法吗? http://stackoverflow.com/questions/41618324/windows-service-runs-but-stops-processing-after-two-days – 2017-01-13 09:28:00

4

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

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

HTH。

+0

+1:在一个单独的库中实现所有的逻辑,并从你的服务中调用它。从控制台应用程序调用相同的库以用于开发/调试目的。 – 2011-02-28 12:21:28

+2

我喜欢你的方法,但它不是调试服务启动问题的唯一方法。我所做的 - 特别是在生产环境中调试服务时 - 是要将WinDbg设置为:1.在主机进程启动时连接到服务,以及2.打开侦听端口(需要克服服务隔离)。然后,可以使用在您的用户会话下运行的另一个WinDbg实例开始调试。 (作为第一条语句的可调参数“RequestAdditionalTime”或注册表配置有助于克服SCM在服务启动时间期限内的时间限制) – 2013-09-02 22:06:15

51

我已经来到这个线程比较晚,但我认为它可能是值得提供一个解释,其他答案都没有。

在OP代码示例中未命中CurrentDomain_UnhandledException处理程序的原因在于调用OnStart方法以响应来自Windows服务控制管理器的启动命令(该命令通过框架的接收和分派到此方法ServiceBase实现);在基类中处理由OnStart引发的任何异常,并将其记录到事件日志中,并转换成返回给SCM的错误状态代码。所以这个异常永远不会传播到AppDomain的未处理的异常处理程序。

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

+0

看起来像ServiceBase上的ServiceQueuedMainCallback方法会导致此行为。 – 2014-03-10 02:46:28

2

当我在自己的Windows服务上工作时,它已经足够奇怪了。我认为这是因为不受欢迎的例外。目前我正在捕捉文本文件上的无用例外。首先,您必须在C位置创建新的文件ServiceLog.txt,因为它会在文本文件上记录excaptions。通过下面的代码,我得到了所有的无用的例外与他们的行号。

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(); 
     } 
    } 
相关问题