I have a Windows Service which I install using the InstallUtil.exe. Even though I have set the Startup Method to Automatic, the service does not start when installed, I have to manually open the services and click start. Is there a way to start it either via the command line, or through the code of the Service?
13 Answers
In your Installer class, add a handler for the AfterInstall event. You can then call the ServiceController in the event handler to start the service.
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();
}
}
Now when you run InstallUtil on your installer, it will install and then start up the service automatically.
After refactoring a little bit, this is an example of a complete windows service installer with automatic start:
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();
}
}
}
Programmatic options for controlling services:
- Native code can used, "Starting a Service". Maximum control with minimum dependencies but the most work.
- WMI: Win32_Service has a
StartService
method. This is good for cases where you need to be able to perform other processing (e.g. to select which service). - PowerShell: execute
Start-Service
viaRunspaceInvoke
or by creating your ownRunspace
and using itsCreatePipeline
method to execute. This is good for cases where you need to be able to perform other processing (e.g. to select which service) with a much easier coding model than WMI, but depends on PSH being installed. - A .NET application can use
ServiceController
Use ServiceController to start your service from code.
Update: And more correct way to start service from the command line is to use "sc" (Service Controller) command instead of "net".
Despite following the accepted answer exactly, I was still unable to get the service to start-- I was instead given a failure message during installation stating that the service that was just installed could not be started, as it did not exist, despite using this.serviceInstaller.ServiceName
rather than a literal...
I eventually found an alternative solution that makes use of the command line:
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();
}
Here is a procedure and code using generated ProjectInstaller
in Visual Studio:
- Create Windows Service project in Visual Studio
- Generate installers to the service
- Open
ProjectInstaller
in design editor (it should open automatically when installer is created) and set properties of generatedserviceProcessInstaller1
(e.g. Account: LocalSystem) andserviceInstaller1
(e.g. StartType: Automatic) - Open
ProjectInstaller
in code editor (pressF7
in design editor) and add event handler toServiceInstaller.AfterInstall
- see the following code. It will start the service after its installation.
ProjectInstaller class:
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();
}
}
}
You can use the GetServices
method of ServiceController
class to get an array of all the services. Then, find your service by checking the ServiceName
property of each service. When you've found your service, call the Start
method to start it.
You should also check the Status
property to see what state it is already in before calling start (it may be running, paused, stopped, etc..).
Just a note: You might have set up your service differently using the forms interface to add a service installer and project installer. In that case replace where it says serviceInstaller.ServiceName with "name from designer".ServiceName.
You also don't need the private members in this case.
Thanks for the help.
This is OK for me. In Service project add to 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();
}
}
}