tru*_*ker 5 c# service callstack exception-handling unmanaged
我有基于类 ServiceBase 的常规 C# 服务。此服务在启动时加载 c++ 动态链接库。有时会发生服务在非托管代码中崩溃。不幸的是,事件查看器仅对此进行了非常简短的描述。如果他的消息是这样的:
应用程序:StreamMapService.exe 框架版本:v4.0.30319 描述:由于未处理的异常,进程被终止。异常信息:异常代码 c0000005,异常地址 00000012"。
99% 确定问题出在非托管代码中。问题是这种情况很少发生(通常每天一次),并且仅在作为服务运行时发生。在调试器下一切正常。为了找出有问题的代码,我按以下方式编辑了我的主要方法:
static void Main()
{
try
{
if (!Environment.UserInteractive)
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
else
{
var services = new Service1();
services.Start();
Console.WriteLine("Press return to exit");
Console.ReadLine();
services.Stop();
}
}
catch (SEHException e)
{
// wrapper for all exceptions having its origin in unmanaged code
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Crash time: {0}\n", DateTime.Now.ToString());
sb.AppendFormat("\nMessage:\n{0}", e.Message);
sb.AppendFormat("\nSource: {0}\n", e.Source);
sb.AppendFormat("Stack trace:\n{0}", e.StackTrace);
sb.AppendFormat("\nTarget site:{0}", e.TargetSite);
SmtpClient client = new SmtpClient("mail.domain.com");
MailAddress from = new MailAddress("sender@domain.com", "sender", System.Text.Encoding.UTF8);
MailAddress to = new MailAddress("receiver@domain.com");
MailMessage message = new MailMessage(from, to);
message.Body = sb.ToString();
message.Subject = "StreamMapService crash info";
client.Send(message);
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
为了测试这个异常处理程序,我在非托管代码的某些部分生成了测试异常。当我在调试器下或从命令行运行服务时,一切正常。
我收到有关异常信息的电子邮件(最重要的是它包含非托管异常起源的调用堆栈)。
但是当我将此程序作为系统服务运行时(从控制面板 -> 管理工具 -> 服务),该服务明显崩溃(它在 tcp 界面上变得无响应,事件查看器也包含崩溃信息)但我没有收到任何电子邮件。
在这种情况下,似乎甚至没有调用异常处理程序。我试图将异常信息写入文件,但也会发生同样的情况。
因此,在调试器下或从命令行运行时,会正确记录调用堆栈信息。当作为系统服务运行时,什么也没有发生。在这种情况下,异常处理似乎无法正常运行。
该异常可能是在另一个线程上引发的。尝试在代码之前添加以下内容以捕获任何未处理的异常:
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Run Code Online (Sandbox Code Playgroud)
事件处理程序应具有以下签名:
void CurrentDomain_UnhandledException(
object sender, UnhandledExceptionEventArgs e) {
}
Run Code Online (Sandbox Code Playgroud)