如何在Windows服务中设置.NET UnhandledException处理?
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服务中将一个debugging器附加到上面的代码中,在CurrentDomain_UnhandledException中设置了一个断点,但是它从未被命中。 popup的exception说它是未处理的,然后服务停止。 我甚至尝试在事件处理程序中放置一些代码,以防它被优化掉。
这是不是在Windows服务中设置未处理的exception处理的正确方法?
我已经来到这个线程比较晚,但我认为这可能是值得提供的解释,其他答案都没有。
在OP代码示例中没有命中CurrentDomain_UnhandledException
处理程序的原因是,响应于来自Windows服务控制pipe理器的启动命令(通过框架的ServiceBase实现接收和分派该命令)调用OnStart
方法; OnStart
引发的任何exception都在基类中处理,logging到事件日志中,并转换成返回给SCM的错误状态代码。 所以这个exception不会传播到AppDomain的未处理的exception处理程序。
我想你会发现从您的服务中的工作线程抛出的未处理的exception将被CurrentDomain_UnhandledException
处理程序捕获。
在Windows服务中,您不希望在OnStart方法中运行很多代码。 所有你想要的是代码来启动你的服务线程,然后返回。
如果你这样做,你可以处理你的服务线程中发生的exception。
例如
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服务的个人经验来添加一些注释是有用的。 最好的方法是避免在服务控制pipe理器下进行开发 – 为此,您需要一个模拟服务开始方式的简单模式 – 可以创build您的服务类实例(您已经从ServiceBase派生出来的实例)并调用你的OnStart,OnStop等方法。 这个线束可以是一个控制台应用程序或Windows应用程序,如你所愿。
这几乎是我发现在.NET中debugging服务启动问题的唯一方法 – 您的代码,Visual Studio和真正的服务控制pipe理器之间的交互只是使这个过程不可能。
HTH。
只是好奇,你想完成什么:避免服务崩溃,或报告错误?
对于报告,我认为你最好的select是添加顶级的try / catch语句。 您可以尝试将它们logging到Windows事件日志和/或日志文件中。
您也可以将ExitCode属性设置为非零值,直到您成功停止该服务。 如果系统pipe理员从“服务”控制面板启动您的服务,并且服务突然停止并显示非零退出代码,则Windows可以显示错误消息和错误说明。
当我在自己的Windows服务器上工作时,它已经足够奇怪了。 我以为这是因为不受欢迎的例外。 目前我正在捕捉文本文件上的无用的例外。 首先,您必须在C位置创build新的文件ServiceLog.txt,因为在文本文件上logging了相关信息。 随着下面的编码,我得到了所有与他们行号无关的例外。
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(); } }