サービスの停止
次はサービスの停止について考えてみましょう。まずは基本の関数です。
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
objWinServ
には、起動の場合と同様の例外処理と待ち時間を設定しています。
先ほどと同じ関数を使用して、サービスが存在するか事前にチェックできます。ただし、サービスの停止時には、そのサービスが停止すべき子サービスを持っているかを確認する必要があります。この処理を行うプロシージャは次のとおりです。
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
このプロシージャには、2つ目の属性NextService
を追加しました。この属性は、子サービスのチェックルーチンを再利用しやすくするためのものです。ステータスを継続に変更したい場合も、子サービスが存在するかを確認する必要があります。そこで、ステータスとしてStop
またはContinue
の値を取る属性情報を追加します。
次に示すのは、サービスを継続させるためのプロシージャです。一時停止させるプロシージャも同様に記述できます。
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
各ステータスのプロシージャを呼び出す汎用関数を次に示します。
Public Function ControlServices(ByVal sServiceName As String, _ ByVal sTask As String, ByVal MachineName As String) Status = "" Dim objWinServ As New ServiceController objWinServ.ServiceName = sServiceName objWinServ.MachineName = MachineName Select Case sTask Case "Reset" If objWinServ.Status = ServiceControllerStatus.Running Then 'Service is currently running, so you will have to 'stop it before starting it 'First stop all it's child services, then stop the 'service itself Call CheckForChildServices(objWinServ, "Stop") End If If objWinServ.Status = ServiceControllerStatus.Stopped Then 'This is satisfied if the service was running and then 'was stopped by code or if it was already stopped. 'Service is already stopped, so just start it... 'so first start all it's parent services Call CheckForParentServices(objWinServ) If Status = "" Then Status = "Successfully Started" Else Status = Status '"Could not Start " & _ objWinServ.DisplayName End If End If Case "Start" If objWinServ.Status = ServiceControllerStatus.Stopped Then 'This is satisfied if the service was running and then 'was stopped by code or if it was already stopped Call CheckForParentServices(objWinServ) If Status = "" Then Status = "Could not Start " & _ objWinServ.DisplayName Else Status = "Successfully Started" End If End If Case "Stop" If objWinServ.Status = ServiceControllerStatus.Running Then Call CheckForChildServices(objWinServ, "Stop") Status = "Successfully Stopped" ElseIf objWinServ.Status = ServiceControllerStatus.Stopped Then Status = "Successfully Stopped" Else Status = "Could not Stop " & objWinServ.DisplayName End If End Select Return Status End Function
これで、リモートからのサービス制御に必要なコードはほぼ揃いました。単にステータスを調べたい場合は、次のように記述することもできます。
Public Function GetServiceStatus(ByVal sServername As String, _ ByVal sServiceName As String) As String Dim ServiceStatus As New ServiceController ServiceStatus.ServiceName = sServiceName ServiceStatus.MachineName = sServername Try If ServiceStatus.Status = ServiceControllerStatus.Running Then Return "Running" ElseIf ServiceStatus.Status = _ ServiceControllerStatus.Stopped Then Return "Stopped" Else Return "Intermidiate" End If Catch ex As Exception Return "Stopped" Finally ServiceStatus = Nothing End Try End Function