简体   繁体   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)
{
}

I attached a debugger to the above code in my windows service, setting a breakpoint in CurrentDomain_UnhandledException, but it was never hit. 我在我的Windows服务中将调试器附加到上面的代码,在CurrentDomain_UnhandledException中设置断点,但它从未被命中。 The exception pops up saying that it is unhandled, and then the service stops. 弹出的异常是说它未处理,然后服务停止。 I even tried putting some code in the event handler, in case it was getting optimized away. 我甚至尝试在事件处理程序中放入一些代码,以防它被优化掉。

Is this not the proper way to set up unhandled exception handling in a windows service? 这不是在Windows服务中设置未处理的异常处理的正确方法吗?

The reason that the UnhandledException event on the current AppDomain does not fire is how services are executed. 当前AppDomain上的UnhandledException事件未触发的原因是服务的执行方式。

  1. User sends a Start command from the Windows Service Control Manager (SCM). 用户从Windows服务控制管理器(SCM)发送“启动”命令。
  2. The command is received by the framework's ServiceBase implementation and dispatched to the OnStart method. 该命令由框架的ServiceBase实现接收,并分派给OnStart方法。
  3. The OnStart method is called. 调用OnStart方法。

Any exception which is thrown by OnStart is handled in the base class , logged to the Event Log, and translated into an error status code returned to the SCM. OnStart抛出的任何异常都在基类中处理 ,记录到事件日志中,并转换为返回给SCM的错误状态代码。 So the exception never propagates to the AppDomain's unhandled exception handler. 因此,异常永远不会传播到AppDomain的未处理异常处理程序。

I think you would find that an unhandled exception thrown from a worker thread in your service would be caught by the AppDomain's unhandled exception handler. 我认为您会发现从您的服务中的工作线程抛出的未处理异常被AppDomain的未处理异常处理程序捕获。

In a Windows Service you do NOT want to be running much code in the OnStart method. 在Windows服务中,您不希望在OnStart方法中运行太多代码。 All you want there is the code to launch your service thread and then return. 您只需要启动服务线程然后返回的代码。

If you do that you can handle exceptions that happen in your service thread just fine. 如果这样做,您可以处理服务线程中发生的异常。

eg 例如

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

Know this thread is a bit old, but thought it would be useful to add some comments based on personal experience developing Windows services in .NET. 知道这个线程有点旧,但认为根据在.NET中开发Windows服务的个人经验添加一些注释会很有用。 The best approach is to avoid developing under the Service Control Manager as much as you can - for this you need a simple harness that mimics the way services get started - something that can create an instance of your service class (that you already derived from ServiceBase) and call your OnStart, OnStop etc methods. 最好的方法是尽可能避免在服务控制管理器下进行开发 - 为此你需要一个模拟服务启动方式的简单工具 - 可以创建服务类实例的东西(你已经从ServiceBase派生的) )并调用您的OnStart,OnStop等方法。 This harness can be a console app or a Windows app as you desire. 根据需要,此线束可以是控制台应用程序或Windows应用程序。

This is pretty much the only way I have found of debugging service start-up issues in .NET - the interaction between your code, Visual Studio and the real Service Control Manager just makes the process impossible otherwise. 这几乎是我在.NET中调试服务启动问题的唯一方法 - 您的代码,Visual Studio和真正的服务控制管理器之间的交互只会使该过程无法实现。

HTH. HTH。

When I was working on my own Windows Service, it was stoping itself oddly enough. 当我在自己的Windows服务上工作时,它已经奇怪地停止了。 I thought it was because of unhanded exception. 我以为是因为无耻的例外。 At the moment I am catching unhanded exceptions on text file. 目前我正在文本文件中捕获无法处理的异常。 First of all you have to create new file ServiceLog.txt on C locations due to logging excaptions on text file. 首先,由于在文本文件上记录了excaptions,您必须在C位置创建新文件ServiceLog.txt。 With below coding I got all unhanded exceptions with them line numbers. 在下面的编码中,我得到了所有未加掩盖的例外情况。

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

Just curious, what are you trying to accomplish: avoiding service crashing, or reporting errors? 只是好奇,你想要完成什么:避免服务崩溃,或报告错误?

For reporting, I think your best bet is to add top-level try/catch statements. 对于报告,我认为最好的办法是添加顶级的try / catch语句。 You can try to log them to the Windows event log and/or a log file. 您可以尝试将它们记录到Windows事件日志和/或日志文件中。

You can also set the ExitCode property to a non-zero value until you successfully stop the service. 您还可以将ExitCode属性设置为非零值,直到您成功停止服务。 If the system administrator starts your service from the Services control panel, and your service stops suddenly with a non-zero exit code, Windows can show an error message with the description of the error. 如果系统管理员从“服务”控制面板启动服务,并且您的服务突然停止并使用非零退出代码,则Windows可以显示包含错误描述的错误消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM