サービスの停止
次はサービスの停止について考えてみましょう。まずは基本の関数です。
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
