web-dev-qa-db-ja.com

Visual Studioを使用して.net Windowsサービスのインストーラーを作成する方法

Visual Studioを使用して作成したWindowsサービスのインストーラーを作成するにはどうすればよいですか?

132
Kelsey

サービスプロジェクトで次の操作を行います。

  1. ソリューションエクスプローラーで、サービスの.csファイルをダブルクリックします。すべて灰色の画面が表示され、ツールボックスからのドラッグに関する説明が表示されます。
  2. 次に、灰色の領域を右クリックして、インストーラーの追加を選択します。これにより、インストーラプロジェクトファイルがプロジェクトに追加されます。
  3. 次に、ProjectInstaller.csのデザインビューに2つのコンポーネント(serviceProcessInstaller1およびserviceInstaller1)があります。次に、必要に応じて、実行するサービス名やユーザーなどのプロパティを設定する必要があります。

ここで、セットアッププロジェクトを作成する必要があります。最善の方法は、セットアップウィザードを使用することです。

  1. ソリューションを右クリックして、新しいプロジェクトを追加します。[追加]> [新しいプロジェクト]> [セットアップと展開プロジェクト]> [セットアップウィザード]

    a。これは、Visual Studioのバージョンによって若干異なる場合があります。 b。 Visual Studio 2010の場所:インストールテンプレート>その他のプロジェクトタイプ>セットアップと展開> Visual Studioインストーラー

  2. 2番目のステップで、「Windowsアプリケーションのセットアップを作成する」を選択します。

  3. 3番目のステップで、「プライマリ出力...」を選択します
  4. クリックして完了します。

次に、インストーラーを編集して、正しい出力が含まれるようにします。

  1. ソリューションエクスプローラーでセットアッププロジェクトを右クリックします。
  2. [表示]> [カスタムアクション]を選択します。 (VS2008では、[表示]> [エディター]> [カスタムアクション]になります)
  3. カスタムアクションツリーのインストールアクションを右クリックし、[カスタムアクションの追加...]を選択します。
  4. [プロジェクトのアイテムを選択]ダイアログで、[アプリケーションフォルダー]を選択し、[OK]をクリックします。
  5. [OK]をクリックして、[...からのプライマリ出力]オプションを選択します。新しいノードを作成する必要があります。
  6. コミット、ロールバック、およびアンインストールのアクションについて、手順4〜5を繰り返します。

ソリューション内のインストーラープロジェクトを右クリックして[プロパティ]を選択すると、インストーラーの出力名を編集できます。 [出力ファイル名:]を任意の名前に変更します。インストーラプロジェクトも選択し、プロパティウィンドウを見ると、Product NameTitleManufacturerなどを編集できます。

次にインストーラーをビルドすると、MSIとsetup.exeが生成されます。サービスのデプロイに使用するものを選択します。

194
Kelsey

Kelseyの最初の一連の手順に従って、サービスプロジェクトにインストーラークラスを追加しますが、MSIまたはsetup.exeインストーラーを作成する代わりに、サービスを自己インストール/アンインストールします。出発点として使用できる私のサービスの1つのサンプルコードを次に示します。

public static int Main(string[] args)
{
    if (System.Environment.UserInteractive)
    {
        // we only care about the first two characters
        string arg = args[0].ToLowerInvariant().Substring(0, 2);

        switch (arg)
        {
            case "/i":  // install
                return InstallService();

            case "/u":  // uninstall
                return UninstallService();

            default:  // unknown option
                Console.WriteLine("Argument not recognized: {0}", args[0]);
                Console.WriteLine(string.Empty);
                DisplayUsage();
                return 1;
        }
    }
    else
    {
        // run as a standard service as we weren't started by a user
        ServiceBase.Run(new CSMessageQueueService());
    }

    return 0;
}

private static int InstallService()
{
    var service = new MyService();

    try
    {
        // perform specific install steps for our queue service.
        service.InstallService();

        // install the service with the Windows Service Control Manager (SCM)
        ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
    }
    catch (Exception ex)
    {
        if (ex.InnerException != null && ex.InnerException.GetType() == typeof(Win32Exception))
        {
            Win32Exception wex = (Win32Exception)ex.InnerException;
            Console.WriteLine("Error(0x{0:X}): Service already installed!", wex.ErrorCode);
            return wex.ErrorCode;
        }
        else
        {
            Console.WriteLine(ex.ToString());
            return -1;
        }
    }

    return 0;
}

private static int UninstallService()
{
    var service = new MyQueueService();

    try
    {
        // perform specific uninstall steps for our queue service
        service.UninstallService();

        // uninstall the service from the Windows Service Control Manager (SCM)
        ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
    }
    catch (Exception ex)
    {
        if (ex.InnerException.GetType() == typeof(Win32Exception))
        {
            Win32Exception wex = (Win32Exception)ex.InnerException;
            Console.WriteLine("Error(0x{0:X}): Service not installed!", wex.ErrorCode);
            return wex.ErrorCode;
        }
        else
        {
            Console.WriteLine(ex.ToString());
            return -1;
        }
    }

    return 0;
}
47
user10256

Visual Studio 2015コミュニティでは、ケルシーもブレンダンのソリューションも機能しません。

インストーラーでサービスを作成する方法を簡単に説明します。

  1. Visual Studioを実行して、 File->New->Project
  2. .NET Framework 4を選択し、[インストール済みテンプレートの検索]タイプで'Service'
  3. 「Windowsサービス」を選択します。名前と場所を入力します。押す OK
  4. Service1.csをダブルクリックし、デザイナーで右クリックして、「インストーラーの追加」を選択します
  5. ProjectInstaller.csをダブルクリックします。 serviceProcessInstaller1の[プロパティ]タブを開き、[アカウント]プロパティ値を[ローカルサービス]に変更します。 serviceInstaller1の場合、「ServiceName」を変更し、「StartType」を「Automatic」に設定します。
  6. ServiceInstaller1をダブルクリックします。 Visual StudioはserviceInstaller1_AfterInstallイベントを作成します。コードを書く:

    private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
    {
        using (System.ServiceProcess.ServiceController sc = new 
        System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName))
        {
            sc.Start();
        }
    }
    
  7. ビルドソリューション。プロジェクトを右クリックし、「エクスプローラーでフォルダーを開く」を選択します。 bin\Debugに移動します。

  8. 以下のスクリプトでinstall.batを作成します。

    :::::::::::::::::::::::::::::::::::::::::
    :: Automatically check & get admin rights
    :::::::::::::::::::::::::::::::::::::::::
    @echo off
    CLS 
    ECHO.
    ECHO =============================
    ECHO Running Admin Shell
    ECHO =============================
    
    :checkPrivileges 
    NET FILE 1>NUL 2>NUL
    if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges ) 
    
    :getPrivileges 
    if '%1'=='ELEV' (shift & goto gotPrivileges)  
    ECHO. 
    ECHO **************************************
    ECHO Invoking UAC for Privilege Escalation 
    ECHO **************************************
    
    setlocal DisableDelayedExpansion
    set "batchPath=%~0"
    setlocal EnableDelayedExpansion
    ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs" 
    ECHO UAC.ShellExecute "!batchPath!", "ELEV", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs" 
    "%temp%\OEgetPrivileges.vbs" 
    exit /B 
    
    :gotPrivileges 
    ::::::::::::::::::::::::::::
    :START
    ::::::::::::::::::::::::::::
    setlocal & pushd .
    
    cd /d %~dp0
    %windir%\Microsoft.NET\Framework\v4.0.30319\InstallUtil /i "WindowsService1.exe"
    pause
    
  9. Uninstall.batファイルを作成します(pen-ult行の/i/uに変更します)。
  10. サービスをインストールして開始するにはinstall.batを実行し、停止してアンインストールするにはuninstall.batを実行します。
22
Alexey Obukhov

VS2017の場合、「Microsoft Visual Studio 2017 Installer Projects」VS拡張機能を追加する必要があります。これにより、追加のVisual Studio Installerプロジェクトテンプレートが提供されます。 https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects#overview

Windowsサービスをインストールするには、新しいセットアップウィザードタイプのプロジェクトを追加し、ケルシーの答え https://stackoverflow.com/a/9021107/104004 の手順に従うことができます。

9
ljsg

InstallUtilクラス(ServiceInstaller)は、Windows Installerコミュニティによってアンチパターンと見なされています。 Windowsインストーラーにサービスのサポートが組み込まれているという事実を無視するのは、壊れやすいプロセス外の車輪の再発明です。

Visual Studio展開プロジェクト(Visual Studioの次のリリースでは高く評価されず、推奨されていません)には、サービスのネイティブサポートがありません。ただし、マージモジュールを使用できます。したがって、このブログ記事を参照して、サービスを表現できるWindows Installer XMLを使用してマージモジュールを作成し、VDPROJソリューションでそのマージモジュールを使用する方法を理解します。

WindowsインストーラーXMLを使用したInstallShieldの拡張-Windowsサービス

IsWiX Windowsサービスチュートリアル

IsWiX Windowsサービスビデオ

1

これは古いスレッドであることは知っていますが、2セントを追加したかっただけです。 VSでサービスプロジェクトを管理する方法は常に嫌いです。これが、私が長年Topshelfを使用してきた理由です。一歩戻り、サービスプロジェクトではなくコンソールプロジェクトを作成してから、Topshelfを追加します。とても簡単です。

https://github.com/Topshelf/Topshelf

0
Paw Baltzersen