goku_da_master
goku_da_master

Reputation: 4307

Issue with Windows service programmatically restarting itself

This question is based on the other question: How can a windows service programmatically restart itself?

I implemented one of the solutions in the previous question like so:

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

I am seeing 2 problems with this:

  1. The event log throws this warning every time the service restarts itself: Windows detected your registry file is still in use by other applications or services... 5 user registry handles leaked from ...
  2. The service might not restart itself sometimes. After looking into it, my best guess is that the service is ending before the process tries to restart it. The reason this is an issue is because the net stop command will fail since the service is already stopped, causing it to not execute the net start command.

Here's the full code:

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 

Assuming I'm correct (big assumption) with issue 2, do you think replacing the Return statement with a Thread.Sleep(10000) command work?

Upvotes: 1

Views: 1053

Answers (1)

KeithS
KeithS

Reputation: 71565

I think the best way to do it this way would be to run a batch file instead of an inline set of commands. That way, the batch file can run "net stop" and get an error, without that error affecting the additional statements being run.

Do you log service "failures" (abnormal terminations) to the event log using the service registration in services.msc? If not, and you simply tell it to "restart the service" if the executable ever exits for any reason, then this is simple; call Application.Exit() instead and the service executable will terminate normally, then Windows will restart it.

As far as registry handles are concerned, if your service is working with registry data, your OnStop method should delay program exit until all handles are cleaned up; that means all background threads must be told to cancel and allowed to do so gracefully (that in turn means the threaded processes must be developed with the ability to be cancelled without simply "killing" them), all open file and registry streams must be closed and properly disposed of, and generally the service must not leave any "frayed ends". OnStop() can delay program execution for about 10 seconds while these things happen; if your service takes longer than that to fully exit, Windows will error out, AND your service will eventually stop but won't be restarted.

Upvotes: 1

Related Questions