【问题标题】:Automatically start a Windows Service on install安装时自动启动 Windows 服务
【发布时间】:2009-06-24 06:33:08
【问题描述】:

我有一个使用 InstallUtil.exe 安装的 Windows 服务。即使我将启动方法设置为自动,安装时服务也不会启动,我必须手动打开服务并单击启动。有没有办法通过命令行启动它,或者通过服务的代码?

【问题讨论】:

    标签: c# windows-services


    【解决方案1】:

    在您的 Installer 类中,为 AfterInstall 事件添加一个处理程序。然后您可以在事件处理程序中调用 ServiceController 来启动服务。

    using System.ServiceProcess;
    public ServiceInstaller()
    {
        //... Installer code here
        this.AfterInstall += new InstallEventHandler(ServiceInstaller_AfterInstall);
    }
    
    void ServiceInstaller_AfterInstall(object sender, InstallEventArgs e)
    {
        ServiceInstaller serviceInstaller = (ServiceInstaller)sender;
    
        using (ServiceController sc = new ServiceController(serviceInstaller.ServiceName))
        {
                 sc.Start();
        }
    }
    

    现在,当您在安装程序上运行 InstallUtil 时,它将自动安装并启动服务。

    【讨论】:

    • (来自建议编辑的评论):最好使用 serviceInstaller.ServiceName,如果服务名称被更改,它将使用正确的名称,而无需在代码中进行更改。
    • ServiceController 包装在 using 语句中也不会有什么坏处。
    • 你是如何获得 serviceInstaller 的?
    • serviceInstaller 应该是您班级中的 ServiceInstaller 变量。此类应实现System.Configuration.Install.Installer。请参阅此msdn guide 了解更多信息。
    • @PhilipRego 推测serviceInstaller是事件处理程序中sender所引用的ServiceInstaller对象,通常在ServiceInstaller()构造函数中实例化。因此,您可以在 using 语句之前添加 ServiceInstaller serviceInstaller = (ServiceInstaller)sender;
    【解决方案2】:

    稍作重构后,这是一个完整的自动启动windows服务安装程序示例:

    using System.ComponentModel;
    using System.Configuration.Install;
    using System.ServiceProcess;
    
    namespace Example.of.name.space
    {
    [RunInstaller(true)]
    public partial class ServiceInstaller : Installer
    {
        private readonly ServiceProcessInstaller processInstaller;
        private readonly System.ServiceProcess.ServiceInstaller serviceInstaller;
    
        public ServiceInstaller()
        {
            InitializeComponent();
            processInstaller = new ServiceProcessInstaller();
            serviceInstaller = new System.ServiceProcess.ServiceInstaller();
    
            // Service will run under system account
            processInstaller.Account = ServiceAccount.LocalSystem;
    
            // Service will have Automatic Start Type
            serviceInstaller.StartType = ServiceStartMode.Automatic;
    
            serviceInstaller.ServiceName = "Windows Automatic Start Service";
    
            Installers.Add(serviceInstaller);
            Installers.Add(processInstaller);
            serviceInstaller.AfterInstall += ServiceInstaller_AfterInstall;            
        }
        private void ServiceInstaller_AfterInstall(object sender, InstallEventArgs e)
        {
            ServiceController sc = new ServiceController("Windows Automatic Start Service");
            sc.Start();
        }
    }
    }
    

    【讨论】:

    • 这段代码给了我以下错误:安装阶段发生异常。 System.InvalidOperationException:System.ServiceProcess.ServiceInstaller 的 OnAfterInstall 事件处理程序发生异常。引发内部异常 System.InvalidOperationException 并显示以下错误消息:无法在计算机“.”上启动服务 serviceName.. 引发内部异常 System.ComponentModel.Win32Exception 并显示以下错误消息:此服务配置为的可执行程序run in 没有实现服务。
    • 在我注释掉“InitializeComponent()”行后发现的错误。我相信这一行复制了所有其他行,因为日志似乎显示在错误之前同时发生了两件相同的事情:安装服务服务名称...服务服务名称已成功安装。在日志Application中创建EventLog源serviceName...正在安装服务serviceName...在日志Application中创建EventLog源serviceName...System.ServiceProcess.ServiceInstaller的OnAfterInstall事件处理程序发生异常。
    • 你真的拯救了我的一天 :) 谢谢你的有用评论。在我注释掉 InitializeComponent() 调用后,我的服务也完美启动了
    【解决方案3】:

    下面的命令怎么样?

    net start "<service name>"
    net stop "<service name>"
    

    【讨论】:

    • 酷。安装完成后,我在我的安装批处理文件中写了这个。
    【解决方案4】:

    控制服务的编程选项:

    • 可以使用本机代码"Starting a Service"。最大程度的控制,最少的依赖,但工作量最大。
    • WMI:Win32_Service 有一个StartService 方法。这适用于您需要能够执行其他处理(例如选择哪个服务)的情况。
    • PowerShell:通过RunspaceInvoke 执行Start-Service 或通过创建自己的Runspace 并使用其CreatePipeline 方法来执行。这适用于您需要能够使用比 WMI 更简单的编码模型执行其他处理(例如选择哪个服务)但取决于安装的 PSH 的情况。
    • .NET 应用程序可以使用ServiceController

    【讨论】:

      【解决方案5】:

      您可以使用以下命令行启动服务:

      net start *servicename*
      

      【讨论】:

        【解决方案6】:

        这是在 Visual Studio 中使用生成的ProjectInstaller 的过程和代码:

        1. Create Windows Service project in Visual Studio
        2. Generate installers to the service
        3. 在设计编辑器中打开ProjectInstaller(它应该在创建安装程序时自动打开)并设置生成的serviceProcessInstaller1(例如Account:LocalSystem)和serviceInstaller1(例如StartType:Automatic)的属性
        4. 在代码编辑器中打开ProjectInstaller(在设计编辑器中按F7)并将事件处理程序添加到ServiceInstaller.AfterInstall - 请参见以下代码。它将在安装后启动服务。

        ProjectInstaller 类:

        using System.ServiceProcess;
        
        
        [RunInstaller(true)]
        public partial class ProjectInstaller : System.Configuration.Install.Installer
        {
            public ProjectInstaller()
            {
                InitializeComponent(); //generated code including property settings from previous steps
                this.serviceInstaller1.AfterInstall += Autorun_AfterServiceInstall; //use your ServiceInstaller name if changed from serviceInstaller1
            }
        
            void Autorun_AfterServiceInstall(object sender, InstallEventArgs e)
            {
                ServiceInstaller serviceInstaller = (ServiceInstaller)sender;
                using (ServiceController sc = new ServiceController(serviceInstaller.ServiceName))
                {
                    sc.Start();
                }
            }
        }
        

        【讨论】:

          【解决方案7】:

          使用ServiceController 从代码启动您的服务。

          更新:从命令行启动服务更正确的方法是使用“sc”(Service Controller)命令而不是“net”。

          【讨论】:

          • 为什么“sc”是一种“更正确”的方式? “net start”(和 start-service PSH cmdlet)有什么问题?
          • 因为 sc 可以从远程机器上调用,所以它总是有效的。
          【解决方案8】:

          尽管完全遵循了接受的答案,但我仍然无法启动服务 - 相反,我在安装过程中收到一条失败消息,指出刚刚安装的服务无法启动,因为它不存在,尽管使用this.serviceInstaller.ServiceName 而不是文字...

          我最终找到了一个使用命令行的替代解决方案:

          private void serviceInstaller_AfterInstall(object sender, InstallEventArgs e) {
                  ProcessStartInfo startInfo = new ProcessStartInfo();
                  startInfo.WindowStyle = ProcessWindowStyle.Hidden;
                  startInfo.FileName = "cmd.exe";
                  startInfo.Arguments = "/C sc start " + this.serviceInstaller.ServiceName;
          
                  Process process = new Process();
                  process.StartInfo = startInfo;
                  process.Start();
              }
          

          【讨论】:

            【解决方案9】:

            自动启动是指服务在Windows启动时自动启动。正如其他人所提到的,要从控制台启动它,您应该使用 ServiceController。

            【讨论】:

            • 我不想这样做。我希望从命令行或 Windows 服务类中一次性完成。
            • 对不起,我错了,我错过了您明确排除通过控制面板启动它的可能性。
            【解决方案10】:

            可以使用ServiceController@987654321@方法 类来获取所有服务的数组。然后,通过检查每个服务的 @987654323@ 属性找到您的服务。找到服务后,调用@987654324@ 方法启动它。

            您还应该检查@987654325@ 属性以查看它在调用 start 之前已经处于什么状态(它可能正在运行、暂停、停止等)。

            【讨论】:

              【解决方案11】:

              你破坏了你的设计师。重新添加您的安装程序组件。它应该有一个 serviceInstaller 和一个 serviceProcessInstaller。属性 Startup Method 设置为 Automatic 的 serviceInstaller 将在安装时和每次重启后启动。

              【讨论】:

                【解决方案12】:

                请注意:您可能使用表单界面以不同方式设置服务,以添加服务安装程序和项目安装程序。在这种情况下,将 serviceInstaller.ServiceName 替换为“来自设计师的名称”.ServiceName。

                在这种情况下,您也不需要私有成员。

                感谢您的帮助。

                【讨论】:

                  【解决方案13】:

                  这对我来说没问题。在 Service 项目中添加到 Installer.cs

                  [RunInstaller(true)]
                  public partial class ProjectInstaller : System.Configuration.Install.Installer
                  {
                      public ProjectInstaller()
                      {
                          InitializeComponent();
                      }
                   
                      protected override void OnAfterInstall(IDictionary savedState)
                      {
                          base.OnAfterInstall(savedState);
                   
                          //The following code starts the services after it is installed.
                          using (System.ServiceProcess.ServiceController serviceController = new System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName))
                          {
                              serviceController.Start();
                          }
                      }
                  }
                  

                  【讨论】:

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