【问题标题】:How to make a .NET Windows Service start right after the installation?如何在安装后立即启动 .NET Windows 服务?
【发布时间】:2010-11-14 19:02:26
【问题描述】:

除了 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。

【问题讨论】:

  • 安装后不启动还是重启后不启动?

标签: .net windows-services installation


【解决方案1】:

为了在安装后立即启动它,我使用 installutil 生成一个批处理文件,然后是 sc start

这并不理想,但它有效....

【讨论】:

    【解决方案2】:

    您需要将自定义操作添加到 MSI 中的“ExecuteImmediate”序列的末尾,使用 EXE 的组件名称或批处理 (sc start) 作为源。我认为 Visual Studio 无法做到这一点,您可能必须使用真正的 MSI 创作工具。

    【讨论】:

      【解决方案3】:

      使用 .NET ServiceController 类来启动它,或者发出命令行命令来启动它——“net start servicename”。无论哪种方式都有效。

      【讨论】:

        【解决方案4】:

        Visual Studio

        如果您正在使用 VS 创建安装项目,您可以创建一个自定义操作,该操作调用 .NET 方法来启动服务。但是,不建议在 MSI 中使用托管自定义操作。看到这个page

        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,您需要在服务组件下添加以下 xml 代码。有关这方面的更多信息,您可以查看此page

        <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】:

          您可以在服务可执行文件中执行所有这些操作,以响应从 InstallUtil 进程触发的事件。覆盖 OnAfterInstall 事件以使用 ServiceController 类来启动服务。

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

          【讨论】:

          • 这是一个不错的解决方案,但仍需要使用 InstallUtil 实用程序。如果您已经在安装过程中提供了 InstallUtil,那么这是最有意义的。但是,如果您想放弃打包 InstallUtil,请使用命令行解决方案。
          【解决方案6】:

          我已经发布了使用 C#here 创建 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 命令行参数运行服务即可安装并启动服务。

          我想我已经涵盖了所有内容,但如果您发现这不起作用,请告诉我,以便我更新答案。

          【讨论】:

          • 请注意,此解决方案不需要使用 InstallUtil.exe,因此您不必将其作为安装程序的一部分提供。
          • 空的“catch { throw; }”子句有什么意义?此外,通过“回滚()”隐藏故障可能不是一个好主意,因为我猜这种情况基本上会使系统处于未定义状态(您尝试安装服务,在中间某处失败并且无法撤消它)。您至少应该向用户“显示”有问题 - 或者 Rollback() 函数是否将一些消息写入控制台?
          • 回滚确实将数据写入控制台。至于空的 catch 块,这是一个调试的东西。我可以在 throw 语句处设置断点来检查可能发生的任何异常。
          • 我收到错误错误:找不到类型或命名空间名称“YourServiceType”(您是否缺少 using 指令或程序集引用?
          • YourServiceType 是您添加到包含ServiceInstallerServiceProcessInstaller 的服务的ProjectInstaller
          【解决方案7】:

          添加到 ScottTx 的答案中,如果您使用 Microsoft way(即使用安装项目等...),以下是启动服务的实际代码。

          (请原谅 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 转换代码真是太好了!
          • 谢谢,这帮助我弄清楚了如何自动启动服务。
          【解决方案8】:

          @Hoàng Long 的 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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-08-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多