2012-02-10 78 views
1

这个问题是基于其他问题: How can a windows service programmatically restart itself?问题与Windows服务程序重新启动本身

我实现的解决方案之一在前面的问题,像这样:

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() 

我看到2个问题与此:

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

下面是完整的代码:

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语句?

回答

1

我认为这样做的最好方法是运行批处理文件而不是内联命令集。这样,批处理文件就可以运行“net stop”并获取错误,而不会影响正在运行的其他语句。

您是否使用services.msc中的服务注册将服务“失败”(异常终止)记录到事件日志中?如果没有,并且只要告诉它“重新启动服务”,如果可执行文件因任何原因退出,那么这很简单;调用Application.Exit(),而服务可执行文件将正常终止,然后Windows将重新启动它。就注册表句柄而言,如果你的服务使用注册表数据,你的OnStop方法应该延迟程序退出,直到所有的句柄都被清除;这意味着所有后台线程必须被告知取消并允许这样做(这意味着线程进程必须能够被取消而不会简单地“杀死”它们),所有打开的文件和注册表流必须被关闭并妥善处置,一般服务不能留下任何“磨损的目的”。当这些事情发生时,OnStop()可以将程序执行延迟约10秒钟;如果您的服务需要比完全退出时间更长的时间,Windows将会出错,并且您的服务最终会停止,但不会重新启动。

+0

+1对于Onstop的信息。有Windows重新启动它是一个好的选择(见其他评论)。我将不得不使用批处理文件进行测试。该服务可以在任何用户帐户(不仅是本地系统)下运行,在这种情况下,该用户可能没有权限执行批处理文件。不确定,但我会测试。 – 2012-02-10 21:20:05

+0

我刚发现不使用批处理文件的另一个原因。安全!如果服务作为具有高权限的用户运行,我想不出一个更简单的方法来破解它。 – 2012-02-16 16:27:30

+0

如果安全性问题,该服务可以发出自己的批处理文件。这在很大程度上排除了攻击者劫持进程以运行恶意批处理文件的能力,并且不会比任何基于运行cmd.exe和Process.Start()的东西更加依赖“魔术字符串”如果命令需要更改,则必须重新构建应用程序的代价。 – KeithS 2012-02-16 16:34:17

0

这一个会帮你吗? (公然自我推销类似的回答我做的) link to answer to similar problem

+0

该选项是“OK”。我不喜欢如何重新启动需要1分钟,并且没有简单的方法来以编程方式设置恢复选项。 – 2012-02-10 21:13:51