Windows服务以编程方式重新启动自身的问题

时间:2012-02-10 19:38:17

标签: .net windows windows-services

此问题基于另一个问题: How can a windows service programmatically restart itself?

我在上一个问题中实现了其中一个解决方案,如下所示:

Dim proc As New Process()
Dim psi As New ProcessStartInfo()

psi.CreateNoWindow = True
psi.FileName = "cmd.exe"
psi.Arguments = "/C net stop YOURSERVICENAMEHERE && net start YOURSERVICENAMEHERE"
psi.LoadUserProfile = False
psi.UseShellExecute = False
psi.WindowStyle = ProcessWindowStyle.Hidden
proc.StartInfo = psi
proc.Start()

我发现有两个问题:

  1. 每次服务重新启动时,事件日志都会抛出此警告: Windows detected your registry file is still in use by other applications or services... 5 user registry handles leaked from ...
  2. 有时,服务可能无法重启。在调查之后,我最好的猜测是服务在进程尝试重新启动之前结束。这是一个问题的原因是因为net stop命令将失败,因为服务已经停止,导致它不执行net start命令。
  3. 这是完整的代码:

    Private Sub Timer_Elapsed(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs) Handles _timer.Elapsed
        ' we do not want the timer stepping on itself (ie. the time interval elapses before the first call is done processing
        _timer.Stop()
    
        ' do some processing here
        Dim shouldRestart As Boolean = ProcessStuff()
    
        If shouldRestart Then
            Dim proc As New Process()
            Dim psi As New ProcessStartInfo()
    
            psi.CreateNoWindow = True
            psi.FileName = "cmd.exe"
            psi.Arguments = "/C net stop ""My Cool Service"" && net start ""My Cool Service"""
            psi.LoadUserProfile = False
            psi.UseShellExecute = False
            psi.WindowStyle = ProcessWindowStyle.Hidden
            proc.StartInfo = psi
            proc.Start()
            Return
        End If
    
        _timer.Start()
    End Sub 
    

    假设我对问题2是正确的(大假设),你认为用Thread.Sleep(10000)命令替换Return语句有效吗?

2 个答案:

答案 0 :(得分:1)

我认为以这种方式执行此操作的最佳方法是运行批处理文件而不是内联命令集。这样,批处理文件可以运行“net stop”并获得错误,而不会影响正在运行的其他语句的错误。

您是否使用services.msc中的服务注册将服务“失败”(异常终止)记录到事件日志中?如果没有,你只是告诉它“重启服务”如果可执行文件因任何原因退出,那么这很简单;相反,调用Application.Exit(),服务可执行文件将正常终止,然后Windows将重新启动它。

就注册表句柄而言,如果您的服务正在使用注册表数据,则OnStop方法应该延迟程序退出,直到清除所有句柄;这意味着必须告知所有后台线程取消并允许优雅地执行此操作(这反过来意味着必须开发线程进程,而不必简​​单地“杀死”它们就可以取消),所有打开的文件和注册表流必须关闭并妥善处置,一般而言,服务不得留下任何“磨损的目的”。在这些事情发生时,OnStop()可以将程序执行延迟大约10秒;如果您的服务需要的时间比完全退出的时间长,Windows将会出错,并且您的服务最终会停止但不会重新启动。

答案 1 :(得分:0)

这个适合你吗? (我公然宣传自我推销的类似答案) link to answer to similar problem