安装时自动启动Windows服务


119

我有使用InstallUtil.exe安装的Windows服务。即使我将“启动方法”设置为“自动”,该服务在安装后也不会启动,我必须手动打开服务并单击“启动”。是否可以通过命令行或通过服务代码来启动它?

Answers:


218

在您的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时,它将安装并自动启动服务。


40
(来自建议的修改的注释):最好使用serviceInstaller.ServiceName,如果servicename被更改,它将使用正确的名称,而无需在代码中对其进行更改。
马克·格雷夫

1
ServiceControllerusing 包装在using语句中也没有什么坏处。
ChrisO 2013年

3
您如何获得serviceInstaller?
菲利普·雷哥

1
serviceInstaller应该是ServiceInstaller您的类中的变量。此类实施System.Configuration.Install.Installer。有关更多信息,请参见此msdn指南
塞尔吉奥·巴苏科

4
@PhilipRego大概serviceInstaller是事件处理程序中所ServiceInstaller引用的对象sender,通常在ServiceInstaller()构造函数中实例化。因此,您可以ServiceInstaller serviceInstaller = (ServiceInstaller)sender;using语句之前添加。
khargoosh

28

重构后,这是一个具有自动启动功能的完整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 Start Type of Manual
        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();
    }
}
}

2
这段代码给了我以下错误:在安装阶段发生异常。System.InvalidOperationException:System.ServiceProcess.ServiceInstaller的OnAfterInstall事件处理程序中发生异常。内部异常System.InvalidOperationException引发了以下错误消息:无法在计算机'。'上启动服务serviceName。内部异常System.ComponentModel.Win32Exception引发了以下错误消息:该服务配置为的可执行程序运行中未实现该服务。
goamn

2
一旦我注释掉“ InitializeComponent()”这一行,就会发现错误。我相信此行正在复制所有其他行,因为日志似乎显示在错误之前一起发生的两个相同的事情:安装服务serviceName ...服务serviceName已成功安装。在日志应用程序中创建EventLog源serviceName ...安装服务serviceName ...在日志应用程序中创建EventLog源serviceName ... System.ServiceProcess.ServiceInstaller的OnAfterInstall事件处理程序中发生异常。
goamn

您真的挽救了我的一天:)感谢您的宝贵意见。在我注释掉InitializeComponent()调用之后,我的服务也开始完美启动
Konstantin

7

如何遵循命令?

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

凉。安装完成后,我在安装批处理文件中写了这个。
M. Fawad Surosh

5

用于控制服务的程序选项:

  • 可以使用本机代码“启动服务”。以最小的依赖关系实现最大程度的控制,但最大程度地发挥作用。
  • WMI:Win32_Service有一个StartService方法。这对于需要执行其他处理(例如选择哪个服务)的情况很有用。
  • PowerShell:Start-Service通过RunspaceInvoke或通过创建自己的Runspace并使用其CreatePipeline方法执行来执行。这对于需要能够以比WMI更简单的编码模型执行其他处理(例如,选择哪个服务)的情况很有用,但取决于安装的PSH。
  • .NET应用程序可以使用 ServiceController


2

使用ServiceController从代码启动服务。

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


6
为什么“ sc”是“更正确”的方式?“ net start”(和启动服务PSH cmdlet)有什么问题?
理查德

1
由于sc可以从远程计算机上调用,因此它始终可以工作。
MacGyver 2015年

1

尽管严格按照已接受的答案进行操作,但我仍然无法启动该服务-安装过程中出现一条失败消息,提示我无法启动刚刚安装的服务,因为即使使用了该服务,该服务也不存在 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();
    }

0

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


我不想这样做。我希望通过命令行或Windows Service类一次完成此操作。
mickyjtwin

抱歉,不好意思,我错过了您明确排除在控制面板上启动它的可能性。
Michael Klement

0

您可以使用ServiceController 类的GetServices方法来获取所有服务的数组。然后,通过检查每个服务的属性来找到您的服务。找到服务后,请致电ServiceNameStart方法以启动它。

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


0

您破坏了设计师。重新添加您的安装程序组件。它应该具有serviceInstaller和serviceProcessInstaller。将属性“启动方法”设置为“自动”的serviceInstaller将在安装后以及每次重新启动后启动。


0

请注意:您可能已经使用Forms界面添加服务安装程序和项目安装程序的方式对服务进行了不同的设置。在这种情况下,将显示为serviceInstaller.ServiceName的位置替换为“来自设计器的名称” .ServiceName。

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

谢谢您的帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.