web-dev-qa-db-ja.com

1つのexeファイルで複数のWindowsサービス

さまざまなことを行うために、いくつかのWindowsサービスを構築しようとしています。たとえば、次のようなWindowsサービスが必要です。

  1. メールで日報を送る
  2. アーカイブされた情報を30分ごとに定期的にクリーンアップします
  3. 等.

Windowsサービスで実行する必要のあるタスクは異なるため、すべてを1つのサービスにまとめるというアイデアはあまり好きではありません。

これまでのところ、Visual Studio 2008のプロジェクトがあります。Windowsサービスを作成し、OnStartイベントにタイマーを設定しました(テスト目的で5秒ごとにテキストファイルに書き込むだけです)。次に、インストーラーをプロジェクトに追加しました。InstallUtil.exeを実行すると、すべて正常に動作します。

同じプロジェクトに2つ目のWindowsサービスを追加すると、問題が発生します。同じログ情報を使用してOnStartコードを再度設定しました(ログに書き込んでいるサービスがわかるように少し異なります)。 2番目のWindowsサービスで、Program.csのメインイベントを次のように変更しました。

    static void Main(string[] args)
    {
        ServiceBase[] ServicesToRun = new ServiceBase[] 
        { 
            new Service1()
        };

        ServiceBase.Run(ServicesToRun);
    }

に:

    static void Main(string[] args)
    {
        ServiceBase[] ServicesToRun = new ServiceBase[] 
        { 
            new Service1(),
            new Service2()
        };

        ServiceBase.Run(ServicesToRun);
    }

この時点では、コンパイル時のエラーはありませんが、Service2サービスは何も実行しません...ロギングタスクは起動しません。

2番目のサービスには「インストーラー」が関連付けられていないという事実に絞り込みました。次に、最初のサービスで行った方法でインストーラーを追加しようとしました(つまり、サービスデザイナーを右クリックし、[インストーラーの追加]をクリックします)。ここで、ProjectInstaller.csファイルに移動すると、そこに別のserviceInstaller(serviceInstaller2)があります。

プロジェクトをビルドしてサービスをインストールしようとすると、[サービス]コントロールパネルウィンドウに移動し、Service1を起動しようとすると、次のエラーメッセージが表示されます。

WindowsはローカルコンピューターでService1サービスを開始できませんでした。

エラー1083:このサービスを実行するように構成されている実行可能プログラムは、サービスを実装していません。

Service2も起動しようとすると、同じエラーメッセージが表示されます(もちろん、エラーメッセージがService2を識別することを除いて)。

1つのexeファイルから2つのサービスを実行するために不足しているものはありますか?

25
dp.

実行可能ファイルを1つ、サービスを2つにする方法を見つけました。各サービスは、独自の名前と開始/停止機能を使用してサービスマネージャーにインストールされます。これがあなたが望んでいることだと思いますよね?これが私がしたことです:

  1. サービスプロジェクトを作成しました。
  2. 同じプロジェクトに2番目のサービスを追加しました(一意のサービス名を使用)。
  3. 両方のサービス(ServiceAとServiceB)にインストーラーを追加しました。
  4. ProjectInstaller.Designer.vbファイルで、Me.Installers.AddRange行を変更して、両方のサービスインストーラーを表示しました。 (Me.ServiceInstaller1、Me.ServiceInstaller2)
  5. メインサービス(私の場合はServiceA)のメインエントリポイントで、ServicesToRun変数を、実行するすべてのサービス(ServiceAとServiceB)を含むServiceBaseの配列に設定します。サービスマネージャがここで引数の数に基づいてプロパティを設定するため、これは重要なステップです。同じexeの複数のインスタンスを許可するか、単一のインスタンスのみを許可します。
  6. インストーラープロジェクトを追加し、サービスの出力を使用します。
  7. サービスからの出力を使用してカスタムアクションを追加します。

ここでデモコードを見つけることができます:
http://code.google.com/p/multi-service-install/

楽しい!

15
Scott

皆さんはすでにこれを解決していると思いますが、他の誰かがそれを必要とする場合に備えて、今日私が数時間かかったこの問題への回答を投稿します。解決策は、別のプロジェクトインストーラーを追加するのではなく、プロジェクトインストーラーのコンポーネントであるサービスインストーラーを追加することです。その新しく追加されたサービスインストーラーには、2番目のサービス名を構成する必要があります。

5
Ogren

今日も同様の問題があり、なんとか解決できました。

まず、各サービスに意味のある一意のServiceNameプロパティがあることを確認しました。ジェネレーターは、両方のサービスに同じ名前を付けましたが、これは役に立ちませんでした。

次に、ProjectInstallerクラスを削除して再生成し、各クラスのインストーラーを追加しました。両方とも静的Mainメソッドでインスタンス化されていることを確認しました。

これで、1つのdllで2つのサービスをインストールできますが、残念ながら、サービスの1つを開始すると、それ自体と他のサービスの両方の機能を実行しているように見えます。つまり、両方のサービスが実行されています(Computer Managerで「開始済み」と表示されるサービスは1つだけですが)。私はまだそれを理解しようとしています...

2
Kirk Broadhurst

私はこれを簡単に達成するためにsc.exeを使用しました。 http://support.Microsoft.com/kb/251192

例:sc create "My Display Service Name" binpath= "c:\app\mysvc.exe --service"

注:「binpath」で確認できるように、すべての等しい値の前にスペースが必要です。

1
Pavan G R

私は実際にあなたが考えているものと非常によく似たものを構築しています。私が(これまでのところ)行うことにしたのは、すべての「サービス」(サービスではありませんが、1つの「コントローラー」は)に特定のインターフェースを実装させることです(init()およびexecute()操作も使用しますFREQUENCY列挙として)。

コントローラはWindowsサービスであり、実行時にxml設定ファイルからプログラム/ dllのリストを読み取り、それらをリストにロードして、定義した頻度でexecute()メソッド(該当する場合)を呼び出します。

私の場合、各プログラムには、ユーザーが制御/変更できるようにするコントローラーのタブページに読み込まれるユーザーコントロールも含まれています。興味があればコードを投稿します。

それが明らかかどうかはわかりません。私は実際に、似たようなものを実装した別のSOユーザーからアイデアを得ましたが、現在その投稿を見つけることができません。

1
Steven Evers

1つの実行可能ファイルに2つの別個の無関係なサービスをインストールすると、私には変なにおいがします。それを機能させることは可能ですが、それは正しくありません。

見たところ、さまざまな間隔でいくつかの異なるタスクを実行する必要があり、タスクは関連している場合と関連していない場合があります。 Quartz.NETを調べましたか?それはあなたのニーズにぴったりのように聞こえます。

http://quartznet.sourceforge.net/features.html

0
Walter

私は今日同じ問題を抱えていて、なんとかそれを修正することができました。私の場合、サービスの* .designer.csファイルを開いて、サービス名が正しく設定されていることを確認する必要がありました。さらに重要なことに、* Installer.Designer.csで、および* Installer.csにコードがある場合は、同じ名前を使用する必要があります。

このエラーは、名前の不一致が原因でのみ発生すると思います。

これがお役に立てば幸いです

0
Usman Akram