如何在安装后立即启动.NET Windows服务?

时间:2009-07-28 17:13:47

标签: .net windows-services installer

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

8 个答案:

答案 0 :(得分:172)

我已经发布了在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命令行参数从命令行(与任何普通应用程序一样)运行服务即可安装并启动服务

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

答案 1 :(得分:21)

您可以在服务可执行文件中执行此操作,以响应从InstallUtil进程触发的事件。重写OnAfterInstall事件以使用ServiceController类来启动服务。

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

答案 2 :(得分:7)

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>

答案 3 :(得分:6)

您需要使用EXE的组件名称或批处理(sc start)作为源,在MSI中的'ExecuteImmediate'序列末尾添加自定义操作。我认为这不能用Visual Studio完成,你可能必须使用真正的MSI创作工具。

答案 4 :(得分:5)

要在安装后立即启动它,我会生成一个包含installutil的批处理文件,然后是sc start

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

答案 5 :(得分:5)

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

答案 6 :(得分:5)

要添加到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事件下。根据经验,这是行不通的。 :)

答案 7 :(得分:-1)

@HoàngLong

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