除了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.
答案 0 :(得分:172)
我已经发布了在C#here中创建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
命令行参数从命令行(与任何普通应用程序一样)运行服务即可安装并启动服务
我想我已经涵盖了所有内容,但是如果您发现这不起作用,请告诉我,以便我可以更新答案。
答案 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