167

C#で記述された標準の.NETWindowsサービスがあります。

InstallUtilを使用せずに自分自身をインストールできますか?サービスインストーラークラスを使用する必要がありますか?どのように使用すればよいですか?

次のように電話できるようにしたいと思います。

MyService.exe -install

そして、それは呼び出すのと同じ効果があります:

InstallUtil MyService.exe
4

7 に答える 7

159

はい、それは完全に可能です(つまり、私はまさにこれを行います)。適切なdll(System.ServiceProcess.dll)を参照し、インストーラークラスを追加するだけです...

次に例を示します。

[RunInstaller(true)]
public sealed class MyServiceInstallerProcess : ServiceProcessInstaller
{
    public MyServiceInstallerProcess()
    {
        this.Account = ServiceAccount.NetworkService;
    }
}

[RunInstaller(true)]
public sealed class MyServiceInstaller : ServiceInstaller
{
    public MyServiceInstaller()
    {
        this.Description = "Service Description";
        this.DisplayName = "Service Name";
        this.ServiceName = "ServiceName";
        this.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
    }
}

static void Install(bool undo, string[] args)
{
    try
    {
        Console.WriteLine(undo ? "uninstalling" : "installing");
        using (AssemblyInstaller inst = new AssemblyInstaller(typeof(Program).Assembly, args))
        {
            IDictionary state = new Hashtable();
            inst.UseNewContext = true;
            try
            {
                if (undo)
                {
                    inst.Uninstall(state);
                }
                else
                {
                    inst.Install(state);
                    inst.Commit(state);
                }
            }
            catch
            {
                try
                {
                    inst.Rollback(state);
                }
                catch { }
                throw;
            }
        }
    }
    catch (Exception ex)
    {
        Console.Error.WriteLine(ex.Message);
    }
}
于 2008-10-31T21:49:56.820 に答える
40

ManagedInstallerクラスのInstallHelperメソッドを見てください。以下を使用してサービスをインストールできます。

string[] args;
ManagedInstallerClass.InstallHelper(args);

これはまさに InstallUtil が行うことです。引数は、InstallUtil と同じです。

この方法の利点は、レジストリをいじることがなく、InstallUtil と同じメカニズムを使用することです。

于 2009-06-18T22:19:14.423 に答える
19

関連する作業の量は自明ではありませんが、いつでも古き良き WinAPI 呼び出しにフォールバックできます。.NET サービスを .NET 対応メカニズムでインストールする必要はありません。

インストールするには:

  • 経由でサービス マネージャーを開きOpenSCManagerます。
  • CreateServiceサービスを登録するために呼び出します。
  • ChangeServiceConfig2オプションで、説明を設定するために呼び出します。
  • でサービスとサービス マネージャ ハンドルを閉じますCloseServiceHandle

アンインストールするには:

  • 経由でサービス マネージャーを開きOpenSCManagerます。
  • を使用してサービスを開きOpenServiceます。
  • DeleteServiceによって返されたハンドルを呼び出して、サービスを削除しOpenServiceます。
  • でサービスとサービス マネージャ ハンドルを閉じますCloseServiceHandle

ServiceInstaller/を使用するよりもこれを好む主な理由ServiceProcessInstallerは、独自のカスタム コマンド ライン引数を使用してサービスを登録できることです。たとえば、それを として登録し"MyApp.exe -service"、ユーザーが引数なしでアプリを実行する場合、サービスをインストール/削除するための UI を提供できます。

Reflector を実行ServiceInstallerすると、この簡単な説明に欠けている詳細を埋めることができます。

PS 明らかに、これには「InstallUtil MyService.exe を呼び出すのと同じ効果」はありません。特に、InstallUtil を使用してアンインストールすることはできません。しかし、おそらくこれはあなたにとって実際には厳しい要件ではなかったようです.

于 2009-11-28T13:39:02.750 に答える
9

これは、サービスを記述するときに使用するクラスです。通常、サービスが呼び出されていないときに表示されるインタラクティブな画面があります。そこから、必要に応じてクラスを使用します。同じマシン上で複数の名前付きインスタンスを許可するため、InstanceID フィールド

サンプルコール

  IntegratedServiceInstaller Inst = new IntegratedServiceInstaller();
  Inst.Install("MySvc", "My Sample Service", "Service that executes something",
                    _InstanceID,
// System.ServiceProcess.ServiceAccount.LocalService,      // this is more secure, but only available in XP and above and WS-2003 and above
  System.ServiceProcess.ServiceAccount.LocalSystem,       // this is required for WS-2000
  System.ServiceProcess.ServiceStartMode.Automatic);
  if (controller == null)
  {
    controller = new System.ServiceProcess.ServiceController(String.Format("MySvc_{0}", _InstanceID), ".");
                }
                if (controller.Status == System.ServiceProcess.ServiceControllerStatus.Running)
                {
                    Start_Stop.Text = "Stop Service";
                    Start_Stop_Debugging.Enabled = false;
                }
                else
                {
                    Start_Stop.Text = "Start Service";
                    Start_Stop_Debugging.Enabled = true;
                }

クラス自体

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Microsoft.Win32;

namespace MySvc
{
    class IntegratedServiceInstaller
    {
        public void Install(String ServiceName, String DisplayName, String Description,
            String InstanceID,
            System.ServiceProcess.ServiceAccount Account, 
            System.ServiceProcess.ServiceStartMode StartMode)
        {
            //http://www.theblacksparrow.com/
            System.ServiceProcess.ServiceProcessInstaller ProcessInstaller = new System.ServiceProcess.ServiceProcessInstaller();
            ProcessInstaller.Account = Account;

            System.ServiceProcess.ServiceInstaller SINST = new System.ServiceProcess.ServiceInstaller();

            System.Configuration.Install.InstallContext Context = new System.Configuration.Install.InstallContext();
            string processPath = Process.GetCurrentProcess().MainModule.FileName;
            if (processPath != null && processPath.Length > 0)
            {
                System.IO.FileInfo fi = new System.IO.FileInfo(processPath);

                String path = String.Format("/assemblypath={0}", fi.FullName);
                String[] cmdline = { path };
                Context = new System.Configuration.Install.InstallContext("", cmdline);
            }

            SINST.Context = Context;
            SINST.DisplayName = String.Format("{0} - {1}", DisplayName, InstanceID);
            SINST.Description = String.Format("{0} - {1}", Description, InstanceID);
            SINST.ServiceName = String.Format("{0}_{1}", ServiceName, InstanceID);
            SINST.StartType = StartMode;
            SINST.Parent = ProcessInstaller;

            // http://bytes.com/forum/thread527221.html
            SINST.ServicesDependedOn = new String[] { "Spooler", "Netlogon", "Netman" };

            System.Collections.Specialized.ListDictionary state = new System.Collections.Specialized.ListDictionary();
            SINST.Install(state);

            // http://www.dotnet247.com/247reference/msgs/43/219565.aspx
            using (RegistryKey oKey = Registry.LocalMachine.OpenSubKey(String.Format(@"SYSTEM\CurrentControlSet\Services\{0}_{1}", ServiceName, InstanceID), true))
            {
                try
                {
                    Object sValue = oKey.GetValue("ImagePath");
                    oKey.SetValue("ImagePath", sValue);
                }
                catch (Exception Ex)
                {
                    System.Windows.Forms.MessageBox.Show(Ex.Message);
                }
            }

        }
        public void Uninstall(String ServiceName, String InstanceID)
        {
            //http://www.theblacksparrow.com/
            System.ServiceProcess.ServiceInstaller SINST = new System.ServiceProcess.ServiceInstaller();

            System.Configuration.Install.InstallContext Context = new System.Configuration.Install.InstallContext("c:\\install.log", null);
            SINST.Context = Context;
            SINST.ServiceName = String.Format("{0}_{1}", ServiceName, InstanceID);
            SINST.Uninstall(null);
        }
    }
}
于 2008-10-31T22:08:05.350 に答える
2

コマンド ライン アプリケーションを Windows サービスとしてインストールしようとする場合は、' NSSM ' ユーティリティを試してください。関連する ServerFault の詳細はこちらにあります

于 2011-10-13T16:35:12.447 に答える