C# 在windows服务中处理AppDomain.CurrentDomain.UnhandledException

C# 在windows服务中处理AppDomain.CurrentDomain.UnhandledException,c#,exception-handling,unhandled-exception,C#,Exception Handling,Unhandled Exception,我有一个窗口服务作为一个同步软件。我想在我的服务中添加未受影响的异常日志记录,因此我修改了我的程序.cs,如下所示: static class Program { /// <summary> /// The main entry point for the application. /// </summary> [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermis

我有一个窗口服务作为一个同步软件。我想在我的服务中添加未受影响的异常日志记录,因此我修改了我的
程序.cs
,如下所示:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
    static void Main()
    {
        // Register Unhandled Exception Handler
        AppDomain.CurrentDomain.UnhandledException +=
            new UnhandledExceptionEventHandler(UnhandledExceptionHandler);

        // Run Service
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new Service() 
        };
        ServiceBase.Run(ServicesToRun);
    }

    static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args)
    {
        // Get Exception
        Exception ex = (Exception)args.ExceptionObject;

        // Generate Error
        string ErrorMessage = String.Format(
            "Error: {0}\r\n" +
            "Runtime Terminating: {1}\r\n----- ----- ----- ----- ----- -----\r\n\r\n" +
            "{2}\r\n\r\n####################################\r\n",
                ex.Message,
                args.IsTerminating,
                ex.StackTrace.Trim());

        // Write Error To File
        try
        {
            using (StreamWriter sw = File.AppendText("UnhandledExceptions.log"))
                sw.WriteLine(errorMessage);
        }
        catch { }
    }
}
静态类程序
{
/// 
///应用程序的主要入口点。
/// 
[SecurityPermission(SecurityAction.Demand,Flags=SecurityPermissionFlag.ControlAppDomain)]
静态void Main()
{
//注册未处理的异常处理程序
AppDomain.CurrentDomain.UnhandledException+=
新的未处理的ExceptionEventHandler(未处理的ExceptionHandler);
//运行服务
ServiceBase[]ServicesToRun;
ServicesToRun=新的ServiceBase[]
{ 
新服务()
};
ServiceBase.Run(ServicesToRun);
}
静态void UnhandledExceptionHandler(对象发送方,UnhandledExceptionEventArgs参数)
{
//破例
异常ex=(异常)args.ExceptionObject;
//产生错误
string ErrorMessage=string.Format(
“错误:{0}\r\n”+
“运行时终止:{1}\r\n-------------------------\r\n\r\n”+
[3 3 7 7 7 7 7 7 7 7 7 7 7 7 3 3 3 3 3 3\\\r\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\#\r\n“,
例如,信息,
args.IsTerminating,
例如StackTrace.Trim());
//文件写入错误
尝试
{
使用(StreamWriter sw=File.AppendText(“UnhandledExceptions.log”))
软件写入线(错误信息);
}
捕获{}
}
}
然后在我的
Service.cs
文件中,在
OnStart
方法中,我添加了一个
抛出新异常(“test”)
查看是否按预期将未处理的异常记录到文件中

当我开始服务时,它会像预期的那样立即停止;但是,它似乎没有将异常记录到指定的文件中

知道我做错了什么吗?提前感谢您的帮助


在您询问之前,我的服务以
Local service
的形式运行,并且运行我的service.exe的目录(c:\mysync)已经在具有完全读/写访问权限的安全选项卡中添加了
Local service

OnStart在try-catch块内的服务基类中调用。如果在此阶段发生异常,它将捕获该异常并将其作为结果设置为状态1,并且不进一步抛出该异常:

  string[] args = (string[]) state;
  try
  {
    this.OnStart(args);
    .....
  }
  catch (Exception ex)
  {
    this.WriteEventLogEntry(Res.GetString("StartFailed", new object[1]
    {
      (object) ((object) ex).ToString()
    }), EventLogEntryType.Error);
    this.status.currentState = 1;
  }
因此,您可以在EventLogs中找到一条记录,但无法将其作为未经处理的域异常捕获,因为不存在此类异常

   using (StreamWriter sw = File.AppendText("UnhandledExceptions.log"))
不使用文件的完整路径名(如c:\foo\bar.log)永远是一个非常糟糕的主意。特别是在服务中,您几乎无法控制服务的默认目录。因为它是由服务控制管理器启动的,而不是由用户从命令提示符或桌面快捷方式启动的

很有可能你只是看错了文件。真正的一个可能最终被写入c:\windows\system32(或syswow64)。操作系统目录通常是写保护的,但这不适用于服务,它们使用高度特权的帐户运行,因此可以在任何地方乱扔硬盘


始终使用完整路径名。强烈建议改用事件日志。

服务框架最有可能捕获异常,因此它不会“未处理”,因此不会触发事件。您的
StreamWriter
实例是否肯定会在处理之前刷新其内容?请尝试使用
文件.AppendAllText(string,string)
方法。感谢您的提示。由于框架捕获到异常,因此未在任何地方编写该方法,请参阅上面的代码。这在很大程度上取决于代码出现的位置。如果它在一个ServiceBase方法重写中,则可以,但在其他任何地方都不可以。这是很可能的情况。它在ServiceBase代码、方法中:private void ServiceQueuedMainCallback(对象状态)。不幸的是,没有办法重写它。当然,这是调用OnStart、OnStop、OnPause等的内部方法。您必须在自己的类中重写这些方法。OnStart()通常启动线程或计时器,OnStop()会再次停止它。这样一个线程中的任何异常都不会自动被记录下来,当然也没有像服务控制器回调中那样的支持。没有发生“未经处理的”异常。正如你所详述的;异常自动记录在事件日志中。谢谢