web-dev-qa-db-ja.com

InstallUtil.exeを使用せずにWindowsサービスをインストールする

私はWindowsサービスを展開しようとしていますが、それを正しく行う方法がわかりません。最初はコンソールアプリとして構築しましたが、今ではWindowsサービスプロジェクトに変換し、サービスのOnStartメソッドからクラスを呼び出すだけです。

Visual Studioがインストールされていないサーバーにこれをインストールする必要があります。これを正しく理解していれば、InstallUtil.exeを使用できず、代わりにインストーラークラスを作成する必要があります。これは正しいです?

以前の質問 InstallUtil.exeを使用せずに.NET Windowsサービスをインストールする を見てきましたが、正しく理解したことを確認したいだけです。

質問の受け入れられた回答がリンクするクラスを作成する場合、次のステップは何ですか? MyService.exeとMyService.exe.configをサーバーにアップロードし、exeファイルをダブルクリックして、Bobが私の叔父ですか?

サービスは1つのサーバーにのみインストールされます。

37
annelie

InstallUtil.exeツールは、サービス内のインストーラーコンポーネントに対するいくつかのリフレクションコールの単なるラッパーです。そのため、実際にはあまり機能しませんが、これらのインストーラーコンポーネントが提供する機能を実行します。 Marc Gravellのソリューションは、コマンドラインからこれを行う手段を提供するだけなので、InstallUtil.exeターゲットマシン上。

これは、マークグラヴェルのソリューションに基づいたステップバイステップです。

インストール直後に.NET Windowsサービスを開始する方法は?

17
Matt Davis

これは非常に古い質問ですが、新しい情報で更新することをお勧めします。

sc コマンドを使用してサービスをインストールできます。

InstallService.bat:

@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

SCを使用すると、さらに多くのことができます。古いサービスをアンインストールし(以前にインストールしたことがある場合)、同じ名前のサービスが存在するかどうかを確認します...サービスを自動起動に設定します。

多くのリファレンスの1つ: sc.exeを使用してサービスを作成する;コンテキストパラメータを渡す方法

私はこの方法とInstallUtilの両方を使いました。個人的には、SCを使用する方がより健康で健康的です。

48
Hoàng Long

Visual Studioなしでもinstallutilを使用できます。これは.netフレームワークに含まれています

サーバーで、管理者としてコマンドプロンプトを開き、次の操作を行います。

CD C:\Windows\Microsoft.NET\Framework\v4.0.version (insert your version)

installutil "C:\Program Files\YourWindowsService\YourWindowsService.exe" (insert your service name/location)

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

installutil /u "C:\Program Files\YourWindowsService\YourWindowsService.exe" (insert your service name/location)
31

セットアッププロジェクトを作成しないのはなぜですか?本当に簡単です。

  1. サービスインストーラーをサービスに追加します(一見役に立たないサービスの「デザイン」面で行います)。
  2. セットアッププロジェクトを作成し、サービス出力をセットアップアプリフォルダーに追加します
  3. 最も重要なのは、Serviceプロジェクトの出力をすべてのカスタムアクションに追加することです。

出来上がり、これで完了です。

詳細については、こちらをご覧ください: http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx

ユーザーに資格情報を要求する(または独自の資格情報を提供する)方法もあります。

5
Doobi

これはサブサービスクラス(ServiceBaseサブクラス)であり、サブクラス化して、installutil.exeなしでコマンドラインから簡単にインストールできるWindowsサービスを構築できます。このソリューションは、 インストール直後に.NET Windowsサービスを開始する方法 から派生し、呼び出し側のStackFrameを使用してサービスタイプを取得するためのコードを追加します。

public abstract class InstallableServiceBase:ServiceBase
{

    /// <summary>
    /// returns Type of the calling service (subclass of InstallableServiceBase)
    /// </summary>
    /// <returns></returns>
    protected static Type getMyType()
    {
        Type t = typeof(InstallableServiceBase);
        MethodBase ret = MethodBase.GetCurrentMethod();
        Type retType = null;
        try
        {
            StackFrame[] frames = new StackTrace().GetFrames();
            foreach (StackFrame x in frames)
            {
                ret = x.GetMethod();

                Type t1 = ret.DeclaringType;

                if (t1 != null && !t1.Equals(t) &&   !t1.IsSubclassOf(t))
                {


                    break;
                }
                retType = t1;
            }
        }
        catch
        {

        }
        return retType;
    }
    /// <summary>
    /// returns AssemblyInstaller for the calling service (subclass of InstallableServiceBase)
    /// </summary>
    /// <returns></returns>
    protected static AssemblyInstaller GetInstaller()
    {
        Type t = getMyType();
        AssemblyInstaller installer = new AssemblyInstaller(
            t.Assembly, null);
        installer.UseNewContext = true;
        return installer;
    }

    private bool IsInstalled()
    {
        using (ServiceController controller =
            new ServiceController(this.ServiceName))
        {
            try
            {
                ServiceControllerStatus status = controller.Status;
            }
            catch
            {
                return false;
            }
            return true;
        }
    }

    private bool IsRunning()
    {
        using (ServiceController controller =
            new ServiceController(this.ServiceName))
        {
            if (!this.IsInstalled()) return false;
            return (controller.Status == ServiceControllerStatus.Running);
        }
    }
    /// <summary>
    /// protected method to be called by a public method within the real service
    /// ie: in the real service
    ///    new internal  void InstallService()
    ///    {
    ///        base.InstallService();
    ///    }
    /// </summary>
    protected void InstallService()
    {
        if (this.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;
        }
    }
    /// <summary>
    /// protected method to be called by a public method within the real service
    /// ie: in the real service
    ///    new internal  void UninstallService()
    ///    {
    ///        base.UninstallService();
    ///    }
    /// </summary>
    protected void UninstallService()
    {
        if (!this.IsInstalled()) return;

        if (this.IsRunning()) {
            this.StopService();
        }
        try
        {
            using (AssemblyInstaller installer = GetInstaller())
            {
                IDictionary state = new Hashtable();
                try
                {
                    installer.Uninstall(state);
                }
                catch
                {
                    throw;
                }
            }
        }
        catch
        {
            throw;
        }
    }

    private void StartService()
    {
        if (!this.IsInstalled()) return;

        using (ServiceController controller =
            new ServiceController(this.ServiceName))
        {
            try
            {
                if (controller.Status != ServiceControllerStatus.Running)
                {
                    controller.Start();
                    controller.WaitForStatus(ServiceControllerStatus.Running,
                        TimeSpan.FromSeconds(10));
                }
            }
            catch
            {
                throw;
            }
        }
    }

    private void StopService()
    {
        if (!this.IsInstalled()) return;
        using (ServiceController controller =
            new ServiceController(this.ServiceName))
        {
            try
            {
                if (controller.Status != ServiceControllerStatus.Stopped)
                {
                    controller.Stop();
                    controller.WaitForStatus(ServiceControllerStatus.Stopped,
                         TimeSpan.FromSeconds(10));
                }
            }
            catch
            {
                throw;
            }
        }
    }
}

しなければならないことは、実際のサービスに2つのパブリック/内部メソッドを実装することです。

    new internal  void InstallService()
    {
        base.InstallService();
    }
    new internal void UninstallService()
    {
        base.UninstallService();
    }

そして、サービスをインストールするときに呼び出します:

    static void Main(string[] args)
    {
        if (Environment.UserInteractive)
        {
            MyService s1 = new MyService();
            if (args.Length == 1)
            {
                switch (args[0])
                {
                    case "-install":
                        s1.InstallService();

                        break;
                    case "-uninstall":

                        s1.UninstallService();
                        break;
                    default:
                        throw new NotImplementedException();
                }
            }


        }
        else {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
            { 
                new MyService() 
            };
            ServiceBase.Run(MyService);            
        }

    }
3
Luca Manzo

Topshelf は、この質問に答えた後に開始されたOSSプロジェクトであり、Windowsサービスを大幅に簡単にします。

http://topshelf-project.com/

1
Doobi

ダブルクリックではなく、正しいコマンドラインパラメーターで実行するので、MyService -i その後 MyService -uをアンインストールします `。

それ以外の場合は、sc.exeを使用してインストールおよびアンインストール(またはInstallUtil.exeに沿ってコピー)できます。

0
Hans Olsson

この問題はセキュリティによるものであり、VS 2012の開発者コマンドプロンプトをRUN AS ADMINISTRATORで開いてサービスをインストールすると、問題が確実に修正されます。

0
Ankur Kumar