C#Windows服务超时启动

我很难确定在用C#创build的Windows服务超时的原因。 我花了相当多的时间在这个问题上看几个post和主题,但我不确定还有什么要尝试。

有什么问题?

有时在运行我的Windows服务的某些机器上,在机器重新启动后,它不会成功启动。 我收到有关服务无法及时启动的公共事件日志消息,并在30000毫秒后超时。 Windows Server 2003机器似乎是最常见的模式,但并不总是孤立于这个操作系统。 例如,它在其他W2K3机器上工作得很好。

启动失败可能是非常随机的,因为有时启动失败,有时启动失败,所以很难按需重现问题。 我也使用Log4Net来捕获和错误,并将它们logging到RollingFileAppender。 但是,如果服务启动失败,则不会创build日志文件,也不会保存日志信息。 这就好像我的服务条目线程被阻塞,没有被调用。

其他详情:

  1. Windows服务用C#编写,并使用.Net 2.0
  2. 安装时,我的服务没有其他服务依赖关系。
  3. service exe是一个Release版本,没有签名或者authenticode签名。
  4. OnStart方法通过创build一个Thread并启动该Thread尽可能快地执行。 OnStart内不会进行其他初始化。
  5. 当服务确实无法启动时,每次打开服务列表并手动启动服务列表,服务开始时间可能不到一秒。

我将以下代码添加到我的Program.cs中,其中包括服务的主要入口点。 我挂钩到CurrentDomain上的一个UnhandledException事件,并使用log4netlogging任何未处理的错误还有一个围绕ServiceBase.Run的try / catch事件popup,以便我可以logging该错误。

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

我inheritance的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> } 

我的log4net实现使用ConsoleAppender和RollingFileAppender,其configuration细节存储在App.config中。

在这个阶段,我不知道还有什么可以尝试的。 如果有更多的细节需要让我知道。

谢谢。

更新:只是为了更新每个人,我会尝试一些build议,如直接login到EventLog或文件,而不是Log4Net,看看是否是原因。 我也会尝试将app.config中的generatePublisherEvidence设置为false。 我只是在等待适当的停机时间访问客户端的服务器来testing这些事情。

我通过关闭配置文件中的发行者证据生成来解决类似的问题。 该服务也没有authenticode签名,但添加下面的行立即解决了问题一直在复制的机器上。

 <runtime> <generatePublisherEvidence enabled="false" /> </runtime> 

还在这个MSDN源码中推荐:
“我们建议服务使用元素来提高启动性能,使用这个元素也可以避免延迟,从而导致超时和取消服务启动

几件事情要尝试:

  • 将日志消息添加到Main()的顶部, ServiceBase.Run()等之前。假设您得到一个日志文件,这些时间戳与Windows事件日志相比如何?

  • 使用“新建项目向导”创建一个全新的服务,并按原样进行部署。 在有问题的机器上,它是否可靠地启动?

  • 获取进程监视器并观察正常启动。 查找任何意外的网络或文件I / O。

  • 确保您的SchedulerService在构造函数中没有任何工作,并且没有任何静态初始化的依赖关系。

  • 将恢复选项设置为首次失败时重新启动。 这是否可靠地工作?

一般来说,从OnStart产生一个后台线程是正确的。

出于故障排除的目的,您可以尝试通过从OnStart调用RequestAdditionalTime方法来为您的服务启动更多的时间。 此外,您可能需要检查是否有任何消息已经写入Windows事件日志(日志“应用程序”,源应该是您的服务名称)。

我也怀疑log4net挂在哪里。 当机器启动时,可能要创建日志的驱动器还没有准备好。 您是否尝试过延迟启动服务?

在这里输入图像说明

由于log4net的设计不是一个可靠的日志记录系统,所以我认为将事件日志(以及日志)的未处理异常(特别是对于服务)写入是一个好习惯。