DOBON.NET

Windows Installer以外のインストーラでWindowsサービスアプリケーションをインストールする

Installerクラスを使用する方法

Visual Studioとセットアッププロジェクト(デプロイメントプロジェクト)を使用した場合、作成したWindowsサービスアプリケーションのインストーラを作成するのはとても簡単です。その方法はMSDNで詳しく説明されています。

この方法によると、「インストーラの追加」リンクをクリックすることにより、プロジェクトにInstallerクラスの派生クラス(ProjectInstallerクラス)を追加し、セットアッププロジェクトの「カスタム動作」にプロジェクトのプライマリ出力を追加するというものです。つまり、ProjectInstallerクラスにより、サービスのインストールとアンインストールを行います。ですので、このProjectInstallerクラスを処理することができれば、セットアッププロジェクトを使う必要がないということになります。

さて、Installerクラスによるカスタム動作がどのように行われるかについては「カスタム動作エディタの使い方」で解説しました。結論を言うと、InstallUtilが使われています。カスタム動作ではInstallUtilLib.dllが使われていますが、InstallUtil.exeを使ってもおなじです。

以上をまとめると、次のような方法でサービスのインストールが可能と言えます。

まずサービスのプロジェクトにProjectInstallerクラスを追加するところまではヘルプと同じです。あとはセットアッププロジェクトのカスタム動作の代わりにInstallUtil.exeを使って、インストール時に

InstallUtil.exe (サービスのEXEファイルのパス)

を、アンインストール時に

InstallUtil.exe /u (サービスのEXEファイルのパス)

を実行すればよいということになります。(つまり、インストール時とアンインストール時に実行ファイルを起動できないインストーラでは残念ながら無理です。)

InstallUtil.exeの場所

ここで新たな問題が発生します。InstallUtil.exeはどこにあるのでしょうか?InstallUtil.exeを配布パッケージに含めることができれば確実ですが、残念ながらInstallUtil.exeは再配布が許可されていません。

そこでここでは、InstallUtil.exeは共通言語ランタイムがインストールされているディレクトリにあるものとして、これを実行するようにします。

共通言語ランタイムがインストールされているディレクトリのパスは、.NET Frameworkバージョン1.1であれば、

(Windowsディレクトリ)\Microsoft.NET\Framework\v1.1.4322

であると決め付けたり、レジストリキー

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework

の「sdkInstallRootv1.1」の値を調べて知ることができます。しかし.NET Frameworkが使えるのであれば、RuntimeEnvironment.GetRuntimeDirectoryメソッドを使うのが確実でしょう。

InstallUtil.exeを起動させる

ここでは、InstallUtil.exeを起動させるために次のようなプログラムをC#で作成し、使用することにします。(ここでは、この実行ファイル名を「instsrv.exe」とします。)

VB.NET
コードを隠すコードを選択
[VB.NET]
VB.NETのコードは現在準備中です。
Convert C# to VB.NET により、
下記のC#のコードをVB.NETに変換したものを参考にしてください。
C#
コードを隠すコードを選択
public class InstallUtil
{
    private static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            ShowError("引数が不正です。");
            return;
        }

        //installutil.exeのフルパスを取得
        string installutilPath =
            System.IO.Path.Combine(
            System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(),
            "installutil.exe");
        if (!System.IO.File.Exists(installutilPath))
        {
            ShowError("installutil.exeが見つかりませんでした。");
            return;
        }

        //installutil.exeに渡すコマンドラインを作成
        string installutilArg = "";
        foreach (string arg in args)
        {
            installutilArg += " " +
                (arg.IndexOf(" ") > -1 ? "\"" + arg + "\"" : arg);
        }

        //installutil.exeを起動
        System.Diagnostics.Process p;
        try
        {
            p = System.Diagnostics.Process.Start(
                installutilPath, installutilArg);
            p.WaitForExit();
        }
        catch
        {
            ShowError("installutil.exeの起動に失敗しました。");
            return;
        }

        if (p.ExitCode != 0)
        {
            ShowError("installutil.exeがエラーコード(" +
                p.ExitCode.ToString() + ")を返しました。");
            return;
        }

        System.Environment.ExitCode = 0;
    }

    private static void ShowError(string msg)
    {
        System.Windows.Forms.MessageBox.Show(
            null,
            msg + "\nサービスのインストール/アンインストールに失敗しました。",
            "エラー",
            System.Windows.Forms.MessageBoxButtons.OK,
            System.Windows.Forms.MessageBoxIcon.Error);
        System.Environment.ExitCode = 1;
    }
}

この「instsrv.exe」をInstallUtil.exeと同じコマンドライン引数で呼び出すことにより、Installerクラスを処理できます。つまり、instsrv.exeを配布パッケージに含め、インストールで配置されるようにし、インストール時に

instsrv.exe (サービスのEXEファイルのパス)

を、アンインストール時に

instsrv.exe /u (サービスのEXEファイルのパス)

を実行すればサービスがインストール・アンインストールされるようになります。

Inno Setupを使用した具体例

具体例をひとつ示しましょう。ここでは「Inno Setup」を使います。

まず[Files]セクションを次のようにします(パスなどは適当に変更してください)。ここでは「WindowsService1.exe」がサービスのEXEファイル名です。instsrv.exeも配布対象にすることを忘れないでください。

[Files]
Source: "C:\WindowsService1.exe"; DestDir: "{app}"
Source: "C:\instsrv.exe"; DestDir: "{app}"

次にインストール時とアンインストール時にinstsrv.exeを起動するために、[Run]と[UninstallRun]セクションを次のようにします。

[Run]
Filename: "{app}\instsrv.exe"; Parameters: "/LogFile= ""{app}\WindowsService1.exe"""

[UninstallRun]
Filename: "{app}\instsrv.exe"; Parameters: "/u /LogFile= ""{app}\WindowsService1.exe"""

これでサービスのインストールとアンインストールが行われるようになるでしょう。

Win32 APIを使用する方法

このようにinstallutil.exeではなく、Win32 APIを使ってサービスをインストール・アンインストールする方法は、次の記事で紹介されています。

Inno SetupのPascal scriptingを使用する方法

Inno SetupのPascal scriptingを使ってサービスをインストール・アンインストールする方法は、次の記事で紹介されています。

NSISのプラグインを使用する方法

NSIS(Nullsoft Scriptable Install System)では、プラグインなどを使ってサービスのインストールとアンインストールができます。詳しくは、「How do I start/stop/create/remove/check a service」をご覧ください。

  • 履歴:
  • 2013/5/9 NSISを追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。
共有する

この記事への評価

この記事へのコメント

この記事に関するコメントを投稿するには、下のボタンをクリックしてください。投稿フォームへ移動します。通常のご質問、ご意見等は掲示板へご投稿ください。