启动时 C# Windows 服务超时
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7009759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# Windows Service Timeout on startup
提问by Apocwhen
I'm having difficulty trying to determine the cause of a timeout in a Windows Service I've created with C#. I've spent a considerable amount of time looking at several posts and topics on the issue but I am unsure what else to try.
我在尝试确定我用 C# 创建的 Windows 服务超时的原因时遇到了困难。我花了大量时间查看有关该问题的几个帖子和主题,但我不确定还可以尝试什么。
What's the problem?
有什么问题?
Sometimes on certain machines which run my windows service, it does not start successfully after the machine has been rebooted. I receive the common EventLog messages about the Service failing to start in a timely fashion and that it timed out after 30000 milliseconds. Windows Server 2003 machines seem to be the most common pattern but is not always isolated to just this OS. For example it works perfectly fine on other W2K3 machines.
有时在某些运行我的 Windows 服务的机器上,它在机器重新启动后无法成功启动。我收到有关服务未能及时启动的常见 EventLog 消息,并且它在 30000 毫秒后超时。Windows Server 2003 机器似乎是最常见的模式,但并不总是仅与此操作系统隔离。例如,它在其他 W2K3 机器上工作得很好。
The startup failure can be quite random in that sometimes it will start, and other times it will fail so it is very difficult to reproduce the issue on demand. I am also using Log4Net to catch and errors and log them to a RollingFileAppender. However, when the service fails to start, no log file is ever created and no log information saved. It is as if my Service entry thread is blocking and not getting called.
启动失败可能是随机的,有时它会启动,有时它会失败,因此很难按需重现问题。我还使用 Log4Net 来捕获错误并将它们记录到 RollingFileAppender。但是,当服务启动失败时,不会创建日志文件,也不会保存日志信息。就好像我的 Service 入口线程正在阻塞并且没有被调用。
Other Details:
其他详情:
- The Windows service is written in C# and uses .Net 2.0
- There are no other service dependencies for my service when installed.
- The service exe is a Release build with no signing or authenticode signing.
- The OnStart method executes as quickly as possible by creating a Thread and starting that Thread. No other initialization takes place within OnStart.
- When the service does actually fail to start, opening the services list and starting it manually works every time and the service starts in probably less than a second.
- Windows 服务使用 C# 编写并使用 .Net 2.0
- 安装时,我的服务没有其他服务依赖项。
- 服务 exe 是一个发布版本,没有签名或验证码签名。
- OnStart 方法通过创建一个线程并启动该线程来尽可能快地执行。OnStart 内不会发生其他初始化。
- 当服务确实无法启动时,打开服务列表并手动启动它每次都可以工作,并且服务可能会在不到一秒钟的时间内启动。
I have the following code added to my Program.cs which include the main entry point for the service. I hook in to an UnhandledException event on the CurrentDomain and am using log4net to log any unhandled errors There's also a try/catch around the ServiceBase.Run in the event it somehow bombs out so that I can log that error.
我将以下代码添加到我的 Program.cs 中,其中包括服务的主要入口点。我连接到 CurrentDomain 上的 UnhandledException 事件并使用 log4net 记录任何未处理的错误 ServiceBase.Run 周围还有一个 try/catch,以防它以某种方式爆炸,以便我可以记录该错误。
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new SchedulerService()
};
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
try
{
ServiceBase.Run(ServicesToRun);
}
catch (Exception ex)
{
Log.Fatal("Unhandled Service Exception", ex);
}
}
private static log4net.ILog _log = null;
static log4net.ILog Log
{
get
{
if (_log == null)
{
if (!log4net.LogManager.GetRepository().Configured)
{
log4net.Config.XmlConfigurator.Configure();
}
_log = log4net.LogManager.GetLogger(typeof(Program));
}
return _log;
}
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception ex = e.ExceptionObject as Exception;
if (ex == null) ex = new Exception(e.ExceptionObject.ToString());
Log.Fatal("Unhandled Service Exception", ex);
}
The code in my inherited ServiceBase implementation is as follows:
我继承的ServiceBase实现中的代码如下:
protected override void OnStart(string[] args)
{
Thread serviceThread = new Thread(new ThreadStart(BackgroundStart));
serviceThread.IsBackground = true;
serviceThread.Start();
}
private void BackgroundStart()
{
//Initialize and start worker objects to perform monitoring...
//<Snip>
}
My log4net implementation is using a ConsoleAppender and a RollingFileAppender where its configuration details are stored in the App.config.
我的 log4net 实现使用的是 ConsoleAppender 和 RollingFileAppender,其配置详细信息存储在 App.config 中。
At this stage I am not sure what else to try. If any more details are needed let me know.
在这个阶段,我不知道还有什么可以尝试的。如果需要更多详细信息,请告诉我。
Thanks.
谢谢。
Update:Just to update everyone, I'm going to try some of the suggestions such as logging to the EventLog directly or a file instead of Log4Net to see if that's the cause. I Will also try setting the generatePublisherEvidence in the app.config to false. I'm just waiting for an appropriate downtime to access the client's server to test these things out.
更新:只是为了更新每个人,我将尝试一些建议,例如直接登录到 EventLog 或文件而不是 Log4Net,以查看是否是原因。我还将尝试将 app.config 中的 generatePublisherEvidence 设置为 false。我只是在等待适当的停机时间来访问客户端的服务器来测试这些东西。
回答by Dmitry
I fixed similar issue by turning off publisher evidence generation in config file. The service also did not have authenticode signing but adding following line immediately fixed the issue on the machine where it has been reproduced consistently.
我通过关闭配置文件中的发布者证据生成解决了类似的问题。该服务也没有验证码签名,但添加以下行立即修复了机器上一致复制的问题。
<runtime>
<generatePublisherEvidence enabled="false" />
</runtime>
Also recommended in this MSDN source:
"We recommend that services use the element to improve startup performance. Using this element can also help avoid delays that can cause a time-out and the cancellation of the service startup. "
此 MSDN 来源中还建议:
“我们建议服务使用该元素来提高启动性能。使用此元素还有助于避免可能导致超时和取消服务启动的延迟。”
回答by Christian.K
In general, spawning a background thread from OnStart
is the right thing to do.
一般来说,从中产生后台线程OnStart
是正确的做法。
For troubleshooting purposes, you could try to give your service more startup time by calling RequestAdditionalTimemethod from OnStart
. Also, you might want to check if any messages have been written to the Windows EventLog (log "Application", the source should be your service name).
出于故障排除目的,您可以尝试通过从调用RequestAdditionalTime方法来为您的服务提供更多启动时间OnStart
。此外,您可能想要检查是否有任何消息已写入 Windows 事件日志(日志“应用程序”,来源应为您的服务名称)。
回答by lnmx
A few things to try:
要尝试的几件事:
Add log messages to the top of
Main()
, beforeServiceBase.Run()
, etc. Assuming you get a log file, how do those timestamps compare to the Windows Event Log?Create a brand new Service with the New Project Wizard and deploy it as-is. On the problem machines, does it start reliably?
Get process monitorand watch a normal startup. Look for any unexpected network or file I/O.
Make sure your
SchedulerService
does not do any work in the constructor, and does not have any statically-initialized dependencies.Set the Recovery options to restart on first failure. Does that work reliably?
将日志消息添加到
Main()
、 beforeServiceBase.Run()
等的顶部。假设您获得了一个日志文件,这些时间戳与 Windows 事件日志相比如何?使用新建项目向导创建一个全新的服务并按原样部署它。在有问题的机器上,它是否可靠地启动?
获取进程监视器并观察正常启动。查找任何意外的网络或文件 I/O。
确保您
SchedulerService
没有在构造函数中做任何工作,并且没有任何静态初始化的依赖项。将恢复选项设置为在第一次失败时重新启动。这工作可靠吗?
回答by Dirk Vollmar
I'd also suspect that log4net is somehow hanging. Maybe the drive where the log is to be created is not ready yet when the machine is booting. Have you tried starting your service delayed?
我还怀疑 log4net 以某种方式挂了。当机器启动时,可能要创建日志的驱动器还没有准备好。您是否尝试过延迟启动服务?
回答by sgmoore
Since log4net is not designed to be (in their words) a reliable logging system, I thought it was good practice to write unhandled exceptions to the eventlog (as well as to your log), especially with services.
由于 log4net 不是(用他们的话说)一个可靠的日志记录系统,我认为将未处理的异常写入事件日志(以及您的日志)是一种很好的做法,尤其是对于服务。