Windowsサービスのインストールとアンインストール
次に、インストールとアンインストールについて考えてみます。最初のステップで、下記のとおりグローバル宣言を行います。
Private Declare Ansi Function WritePrivateProfileString Lib _
"KERNEL32.DLL" Alias "WritePrivateProfileStringA" _
(ByVal lpSectionName As String, ByVal lpKeyName As String, _
ByVal lpKeyValue As String, ByVal lpFileName As String) As Integer
Private Declare Ansi Function GetPrivateProfileString Lib _
"KERNEL32.DLL" Alias "GetPrivateProfileStringA" _
(ByVal lpSectionName As String, ByVal lpKeyName As String, _
ByVal lpDefault As String, _
ByVal lpReturnedString As StringBuilder, _
ByVal nSize As Integer, _
ByVal lpFileName As String) As Integer
サービスをインストールするには、そのサービスを実行するユーザーのユーザー名と証明書、ならびにサービスから呼び出される実行ファイルへのパス情報を渡す必要があります。
Private Sub InstallService(ByVal sServiceName As String)
Try
Console.WriteLine("Running Install Service...")
Dim sUserID As String = sDomainName & "\" & sUserID
Dim sPassword As String = sPassword
If IsServiceInstalled(sServiceName) Then _
UninstallService(sServiceName)
' INSTALL
Dim hSCM As IntPtr = OpenSCManager(Nothing, Nothing, _
ServiceControlManagerEnum.AllAccess)
If hSCM.ToInt32 = 0 Then
Throw New Exception("Could not install service. [1]")
Else
Dim iServiceType As Integer = ServiceTypeEnum.Win32OwnProcess
Dim hService As IntPtr = CreateService(hSCM, sServiceName, _
sServiceName, ServiceControlManagerEnum.AllAccess, _
iServiceType, ServiceTypeEnum.AutoStart, _
ServiceTypeEnum.ErrorNormal, sPath, Nothing, Nothing, _
Nothing, sUserID, sPassword)
If hService.ToInt32 = 0 Then
Throw New Exception("Could not install service. [2]")
Else
CloseServiceHandle(hService)
End If
CloseServiceHandle(hSCM)
Call ControlServices(sServiceName, "Start")
End If
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.ReadLine()
End Try
End Sub
サービスが存在するかどうかの確認は次の関数で行います。
Private Function IsServiceInstalled(ByVal sServiceName As String) _
As Boolean
Dim bResult As Boolean = False
Dim oServiceArray() As ServiceProcess.ServiceController
oServiceArray = ServiceProcess.ServiceController.GetServices
For Each oServiceController _
As ServiceProcess.ServiceController In oServiceArray
If oServiceController.ServiceName.Trim.ToUpper = _
sServiceName.Trim.ToUpper Then
Dim i As New ServiceControllerPermissionAttribute _
(Security.Permissions.SecurityAction.Demand)
Dim d As New ServiceControllerPermission
Try
If d.Any Then
d.ToString()
End If
Catch
End Try
bResult = True
Exit For
End If
Next
Return bResult
End Function
アンインストールを行うプロシージャも、同様のコードで実現できます。
Private Sub UninstallService(ByVal sServiceName As String)
Console.WriteLine("Running Uninstall Service...")
If IsServiceInstalled(sServiceName) Then
' STOP SERVICE
Call ControlServices(sServiceName, "Stop")
Else
Exit Sub
End If
Dim hSCM As IntPtr = OpenSCManager(Nothing, Nothing, _
ServiceControlManagerEnum.AllAccess)
If hSCM.ToInt32 = 0 Then
Throw New Exception("Could not delete service. [1]")
Else
Dim hService As IntPtr = OpenService(hSCM, sServiceName, _
ServiceAccessTypeEnum.AllAccess)
If hService.ToInt32 = 0 Then
' TODO: FAILED
Else
If Not DeleteService(hService) Then
Throw New Exception("Could not delete service. [2]")
End If
CloseServiceHandle(hService)
End If
CloseServiceHandle(hSCM)
End If
End Sub
ログオンユーザーを変更する場合、私の考える最も美しい方法は、サービスをアンインストールしてから、新たな証明書を用いて再インストールすることです。
この記事のダウンロードサンプルには、ここで紹介したすべての関数を含むコンソールアプリケーションの「.sln」ファイルが収録されています。サンプルではアンインストールの関数を呼び出しているだけですが、この記事の内容を参考にすれば、メイン関数に起動/停止などの機能を簡単に追加できるでしょう。
