Install/Uninstall/Control Windows Services Remotely Using VB.Net

Windows services have a few basic properties: They can be configured to run under a specific user. They can have parent or child services; a parent service is a service that your service is dependant on and a child service is a service that depends on your service. This comes into play when you start/stop services. For a clean start, you need to make sure the parent services of your service are started.

For a clean stop, make sure the child services of your service are stopped.

Now, start with the code: To control services in VB.Net, you need to import the service process namespace; therefore, your first line is:

Imports System.ServiceProcess

First, just try to start a service without checking for any dependenciers on parent services.

Dim objWinServ As New ServiceController
objWinServ.ServiceName = sServiceName
objWinServ.MachineName = MachineName
StartService(objWinServ)

Private Sub StartService(ByVal Service As ServiceController)
   If Service.Status = ServiceControllerStatus.Stopped Then
      Try
         Service.Start()
         Service.WaitForStatus(ServiceControllerStatus.Running, _
            System.TimeSpan.FromSeconds(20))
      Catch ex As TimeoutException
         Status = "Could not Start " & Service.DisplayName & _
                  " - TimeOut expired"
      Catch e As Exception
         Status = "Could not Start " & Service.DisplayName & _
                  " - " & e.Message
      End Try

   End If

End Sub

The code is fairly straightforward:

  1. Create a new service controller object called objWinServ.
  2. Assign the servcie name and machine name (because you’re calling it remotely).
  3. Supply the objWinServ object to your start service routine.
  4. The routine first checks the status of the service to see if it is stopped. You can further check to see whether it’s paused, running, and so forth.
  5. Then, it tries to start the service. I’ve put in a max wait of 20 seconds for the service to start. If it does not, it throws an timeout exception. I’ve put in a general exception clause as well.

Now, to make the code more robust, two things you may want to check for are:

  1. Parent Services that need to start before your service
  2. Whether the service actually exists on the server.

To check for parent services that need to be started, you use this recursive sub:

Private Sub CheckForParentServices _
   (ByVal Service As ServiceController)
      Dim objParentService As ServiceController
      For Each objParentService In Service.ServicesDependedOn
         CheckForParentServices(objParentService)
      Next
      Call StartService(Service)
End Sub

Pass objWinServ to the sub and let it do its magic!

To check whether or not the servcie exists, use this function that will return a boolean value depending on whether or not the service exists:

Public Function CheckforService(ByVal ServerName As String, _
   ByVal ServiceName As String) As Boolean
      Dim Exist As Boolean = False
      Dim objWinServ As New ServiceController
      Dim ServiceStatus As ServiceControllerStatus
      objWinServ.ServiceName = ServiceName
      objWinServ.MachineName = ServerName

      Try
         ServiceStatus = objWinServ.Status
         Exist = True
      Catch ex As Exception
      Finally
         objWinServ = Nothing
      End Try
      Return Exist
End Function

Now, look into stopping the service. First, the basic function:

Private Sub StopService(ByVal Service As ServiceController)
   Dim status As String
   If Service.Status = ServiceControllerStatus.Running Then
      Try
         Service.Stop()
         Service.WaitForStatus(ServiceControllerStatus.Stopped, _
                               System.TimeSpan.FromSeconds(20))
      Catch ex As TimeoutException
         status = "Could not Stop " & Service.DisplayName & _
                  "Service - TimeOut expired"
      Catch e As Exception
         status = "Could not Stop " & Service.DisplayName & _
                 "Service - " & e.Message
      End Try
   End If

End Sub

Pass objWinServ, with the same kind of exception handling and wait times.

You can use the same function as earlier to check whether or not the service exists, but when it comes to stopping a service, you need to check if the service has any dependant child servcies that also need to be stopped. The Sub for that is:

Private Sub CheckForChildServices(ByVal Service As ServiceController, _
                                  ByVal NextService As String)

   Dim objChildService As ServiceController

   For Each objChildService In Service.DependentServices
      CheckForChildServices(objChildService, NextService)
   Next

   If NextService = "Stop" Then
      Call StopService(Service)
   Else
      Call ContinueService(Service)
   End If

End Sub

I’ve added a second attribute, ‘NextService’, for this sub. This is to make the child service check sub more reusable. You need to check for child services if you want to change the status to continue as well. So, you add an attribute that can take values of stop or continue.

Here’s the sub for continue service. You can write a similar one for pause as well.

Private Sub ContinueService(ByVal Service As ServiceController)
   Dim status As String
   If Service.Status = ServiceControllerStatus.Paused Then
      Try
         Service.Continue()
         Service.WaitForStatus(ServiceControllerStatus.Running, _
                               System.TimeSpan.FromSeconds(20))
      Catch ex As TimeoutException
         status = "Could not change status from Paused To _
                   Continue for " & Service.DisplayName " _
                  " - TimeOut expired"
      Catch e As Exception
         status = "Could not change status from Paused To _
                   Continue for " & Service.DisplayName & " - " _
                   & e.Message
      End Try
   End If

   If Service.Status = ServiceControllerStatus.Stopped Then
         Call StopService(Service)
   End If

End Sub

More by Author

Must Read