インストール直後に.NET Windowsサービスを開始するにはどうすればよいですか?


88

service.StartType = ServiceStartMode.Automaticに加えて、インストール後にサービスが開始しません

解決

このコードをProjectInstallerに挿入しました

protected override void OnAfterInstall(System.Collections.IDictionary savedState)
{
    base.OnAfterInstall(savedState);
    using (var serviceController = new ServiceController(this.serviceInstaller1.ServiceName, Environment.MachineName))
        serviceController.Start();
}

ScottTxとFrancis Bに感謝します。


インストール直後に起動しない、または再起動しても起動しない?
Chris Van Opstal、2009

回答:


21

これはすべて、InstallUtilプロセスから発生したイベントに応答して、サービス実行可能ファイル内から実行できます。OnAfterInstallイベントをオーバーライドして、ServiceControllerクラスを使用してサービスを開始します。

http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceinstaller.aspx


3
これは優れたソリューションですが、InstallUtilユーティリティを使用する必要があります。インストールの一部として既にInstallUtilを提供している場合、これは最も理にかなっています。ただし、InstallUtilのパッケージ化を中止する場合は、コマンドラインソリューションを使用してください。
マットデイビス

181

私はここにC# Windowsサービスを作成するためのステップバイステップの手順を投稿しまし。少なくともここまで進んでいるようですが、インストールしたサービスをどのように開始するのか疑問に思っています。StartTypeプロパティをAutomaticに設定すると、システムの再起動後にサービスが自動的に開始されますが、(ご存じのように)インストール後にサービスが自動的に開始されません。

最初にそれをどこで見つけたのか覚えていません(おそらくMarc Gravell?)。しかし、実際にサービス自体を実行してサービスをインストールおよび開始できるソリューションをオンラインで見つけました。手順は次のとおりです。

  1. 次のMain()ようにサービスの機能を構成します。

    static void Main(string[] args)
    {
        if (args.Length == 0) {
            // Run your service normally.
            ServiceBase[] ServicesToRun = new ServiceBase[] {new YourService()};
            ServiceBase.Run(ServicesToRun);
        } else if (args.Length == 1) {
            switch (args[0]) {
                case "-install":
                    InstallService();
                    StartService();
                    break;
                case "-uninstall":
                    StopService();
                    UninstallService();
                    break;
                default:
                    throw new NotImplementedException();
            }
        }
    }
  2. サポートコードは次のとおりです。

    using System.Collections;
    using System.Configuration.Install;
    using System.ServiceProcess;
    
    private static bool IsInstalled()
    {
        using (ServiceController controller = 
            new ServiceController("YourServiceName")) {
            try {
                ServiceControllerStatus status = controller.Status;
            } catch {
                return false;
            }
            return true;
        }
    }
    
    private static bool IsRunning()
    {
        using (ServiceController controller = 
            new ServiceController("YourServiceName")) {
            if (!IsInstalled()) return false;
            return (controller.Status == ServiceControllerStatus.Running);
        }
    }
    
    private static AssemblyInstaller GetInstaller()
    {
        AssemblyInstaller installer = new AssemblyInstaller(
            typeof(YourServiceType).Assembly, null);
        installer.UseNewContext = true;
        return installer;
    }
  3. サポートコードを続行しています...

    private static void InstallService()
    {
        if (IsInstalled()) return;
    
        try {
            using (AssemblyInstaller installer = GetInstaller()) {
                IDictionary state = new Hashtable();
                try {
                    installer.Install(state);
                    installer.Commit(state);
                } catch {
                    try {
                        installer.Rollback(state);
                    } catch { }
                    throw;
                }
            }
        } catch {
            throw;
        }
    }
    
    private static void UninstallService()
    {
        if ( !IsInstalled() ) return;
        try {
            using ( AssemblyInstaller installer = GetInstaller() ) {
                IDictionary state = new Hashtable();
                try {
                    installer.Uninstall( state );
                } catch {
                    throw;
                }
            }
        } catch {
            throw;
        }
    }
    
    private static void StartService()
    {
        if ( !IsInstalled() ) return;
    
        using (ServiceController controller = 
            new ServiceController("YourServiceName")) {
            try {
                if ( controller.Status != ServiceControllerStatus.Running ) {
                    controller.Start();
                    controller.WaitForStatus( ServiceControllerStatus.Running, 
                        TimeSpan.FromSeconds( 10 ) );
                }
            } catch {
                throw;
            }
        }
    }
    
    private static void StopService()
    {
        if ( !IsInstalled() ) return;
        using ( ServiceController controller = 
            new ServiceController("YourServiceName")) {
            try {
                if ( controller.Status != ServiceControllerStatus.Stopped ) {
                    controller.Stop();
                    controller.WaitForStatus( ServiceControllerStatus.Stopped, 
                         TimeSpan.FromSeconds( 10 ) );
                }
            } catch {
                throw;
            }
        }
    }
  4. この時点で、ターゲットマシンにサービスをインストールした後、-installコマンドライン引数を指定して(通常のアプリケーションと同様に)コマンドラインからサービスを実行し、サービスをインストールして開始します。

私はすべてをカバーしたと思いますが、これが機能しない場合は、回答を更新できるようにお知らせください。


12
このソリューションではInstallUtil.exeを使用する必要がないため、インストールプログラムの一部として提供する必要はありません。
マット・デイビス

2
空の "catch {throw;}"句の意味は何ですか?また、「Rollback()」でエラーを非表示にすることはおそらくお勧めできません。その状況では、システムが基本的に未定義の状態になるためです(サービスをインストールしようとしましたが、途中で失敗し、元に戻すことができませんでした) )。少なくともユーザーに何か怪しいものがあることを「示す」必要があります-または、Rollback()関数はコンソールにメッセージを書き込みますか?
Christian.K

5
ロールバックはデータをコンソールに書き込みます。空のcatchブロックについては、デバッグ用です。throwステートメントにブレークポイントを配置して、発生する可能性のある例外を調べることができます。
マット・デイビス

4
エラーが発生しましたエラー:タイプまたは名前空間名 'YourServiceType'が見つかりませんでした(usingディレクティブまたはアセンブリ参照がありませんか?
Yogesh

5
YourServiceTypeand ProjectInstallerを含むサービスに追加したものですServiceInstallerServiceProcessInstaller
bansi

6

Visual Studio

VSでセットアッププロジェクトを作成する場合は、.NETメソッドを呼び出してサービスを開始するカスタムアクションを作成できます。ただし、MSIでマネージカスタムアクションを使用することは、実際にはお勧めできません。こちらのページをご覧ください

ServiceController controller  = new ServiceController();
controller.MachineName = "";//The machine where the service is installed;
controller.ServiceName = "";//The name of your service installed in Windows Services;
controller.Start();

InstallShieldまたはWise

InstallShieldまたはWiseを使用している場合、これらのアプリケーションはサービスを開始するオプションを提供します。Wiseの例では、サービスコントロールアクションを追加する必要があります。このアクションでは、サービスを開始するか停止するかを指定します。

Wix

Wixを使用するには、サービスのコンポーネントの下に次のxmlコードを追加する必要があります。詳しくは、こちらのページをご覧ください

<ServiceInstall 
    Id="ServiceInstaller"  
    Type="ownProcess"  
    Vital="yes"  
    Name=""  
    DisplayName=""  
    Description=""  
    Start="auto"  
    Account="LocalSystem"   
    ErrorControl="ignore"   
    Interactive="no">  
        <ServiceDependency Id="????"/> ///Add any dependancy to your service  
</ServiceInstall>

5

EXEのコンポーネント名またはバッチ(sc start)をソースとして使用して、MSIの「ExecuteImmediate」シーケンスの最後にカスタムアクションを追加する必要があります。これはVisual Studioでは実行できないと思います。実際のMSIオーサリングツールを使用する必要があるかもしれません。


4

インストール直後に開始するには、installutilに続いてsc startを使用してバッチファイルを生成します。

理想的ではありませんが、動作します。


4

.NET ServiceControllerクラスを使用して開始するか、コマンドラインコマンドを発行して開始します--- "net start servicename"。どちらの方法でも機能します。


4

ScottTxの答えに追加するために、Microsoftの方法でサービスを開始する場合の実際のコードを次に示します(つまり、セットアッププロジェクトを使用するなど)。

(VB.netコードを失礼しますが、これは私が行き詰まっているものです)

Private Sub ServiceInstaller1_AfterInstall(ByVal sender As System.Object, ByVal e As System.Configuration.Install.InstallEventArgs) Handles ServiceInstaller1.AfterInstall
    Dim sc As New ServiceController()
    sc.ServiceName = ServiceInstaller1.ServiceName

    If sc.Status = ServiceControllerStatus.Stopped Then
        Try
            ' Start the service, and wait until its status is "Running".
            sc.Start()
            sc.WaitForStatus(ServiceControllerStatus.Running)

            ' TODO: log status of service here: sc.Status
        Catch ex As Exception
            ' TODO: log an error here: "Could not start service: ex.Message"
            Throw
        End Try
    End If
End Sub

上記のイベントハンドラーを作成するには、2つのコントロールがあるProjectInstallerデザイナーに移動します。ServiceInstaller1コントロールをクリックします。イベントの下のプロパティウィンドウに移動すると、AfterInstallイベントが見つかります。

注:上記のコードをServiceProcessInstaller1のAfterInstallイベントの下に配置しないでください。経験上、うまくいきません。:)


VB.netコードは悪くありません!複数の言語で作業する私たちにとって、Cからコードを変換する必要がないのは素晴らしいことです。
Steve Reed Sr

おかげで、これは私がサービスを自動的に開始する方法を理解するのに役立ちました。
Charles Owen、

0

最も簡単な解決策は、@HoàngLongによるinstall-windows-service-without-installutil-exeです。

@echo OFF
echo Stopping old service version...
net stop "[YOUR SERVICE NAME]"
echo Uninstalling old service version...
sc delete "[YOUR SERVICE NAME]"

echo Installing service...
rem DO NOT remove the space after "binpath="!
sc create "[YOUR SERVICE NAME]" binpath= "[PATH_TO_YOUR_SERVICE_EXE]" start= auto
echo Starting server complete
pause
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.