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」ファイルが収録されています。サンプルではアンインストールの関数を呼び出しているだけですが、この記事の内容を参考にすれば、メイン関数に起動/停止などの機能を簡単に追加できるでしょう。