如何在安装后立即启动.NET Windows Service?
除了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.
您可以在您的服务可执行文件中完成这一切,以响应从InstallUtil进程触发的事件。 重写OnAfterInstall事件以使用ServiceController类来启动服务。
http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceinstaller.aspx
我已经发布了一个在C#中创建Windows服务的分步过程。 这听起来像是你至少到现在这一点,现在你想知道如何启动服务,一旦安装。 将StartType属性设置为Automatic将导致服务在重新启动系统后自动启动,但不会(如您发现的那样)在安装后自动启动您的服务。
我不记得最初是在哪里找到的(或许是Marc Gravell?),但是我确实在网上找到了一个解决方案,它允许你通过实际运行你的服务本身来安装和启动你的服务。 这是一步一步的:
-
像这样构建你的服务的
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(); } } }
-
这是支持代码:
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; }
-
继续支持代码…
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; } } }
-
此时,在目标机器上安装服务之后,只需使用
-install
命令行参数从命令行(与任何普通应用程序一样)运行服务即可安装并启动服务。
我想我已经涵盖了一切,但如果你发现这不起作用,请让我知道,所以我可以更新答案。
视觉工作室
如果您使用VS创建安装项目,则可以创建一个调用.NET方法来启动该服务的自定义操作。 但是,不建议在MSI中使用托管自定义操作。 看到这个页面 。
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代码。 有关更多的信息,你可以检查这个页面 。
<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>
您需要将自定义操作添加到MSI中“ExecuteImmediate”序列的末尾,使用EXE的组件名称或批处理(sc start)作为源。 我不认为这可以用Visual Studio完成,你可能不得不使用一个真正的MSI创作工具。
要在安装后立即启动它,我使用installutil生成批处理文件,然后使用sc start
这不是理想的,但它的作品….
使用.NET ServiceController类来启动它,或者发出命令行命令来启动它—“net start servicename”。 无论哪种方式工作。
要添加到ScottTx的答案,这是实际的代码来启动服务,如果你是微软的方式 (即使用安装项目等…)
(原谅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事件之下。 这不会起作用,来自经验。 🙂
最简单的解决方法是在这里找到@ 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