How to make a .NET Windows Service start right after the installation?
Solution 1
You can do this all from within your service executable in response to events fired from the InstallUtil process. Override the OnAfterInstall event to use a ServiceController class to start the service.
http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceinstaller.aspx
Solution 2
I've posted a step-by-step procedure for creating a Windows service in C# here. It sounds like you're at least to this point, and now you're wondering how to start the service once it is installed. Setting the StartType property to Automatic will cause the service to start automatically after rebooting your system, but it will not (as you've discovered) automatically start your service after installation.
I don't remember where I found it originally (perhaps Marc Gravell?), but I did find a solution online that allows you to install and start your service by actually running your service itself. Here's the step-by-step:
-
Structure the
Main()
function of your service like this: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(); } } }
-
Here is the supporting code:
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; }
-
Continuing with the supporting code...
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; } } }
At this point, after you install your service on the target machine, just run your service from the command line (like any ordinary application) with the
-install
command line argument to install and start your service.
I think I've covered everything, but if you find this doesn't work, please let me know so I can update the answer.
Solution 3
Visual Studio
If you are creating a setup project with VS, you can create a custom action who called a .NET method to start the service. But, it is not really recommended to use managed custom action in a MSI. See this 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 or Wise
If you are using InstallShield or Wise, these applications provide the option to start the service. Per example with Wise, you have to add a service control action. In this action, you specify if you want to start or stop the service.
Wix
Using Wix you need to add the following xml code under the component of your service. For more information about that, you can check this 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>
Solution 4
You need to add a Custom Action to the end of the 'ExecuteImmediate' sequence in the MSI, using the component name of the EXE or a batch (sc start) as the source. I don't think this can be done with Visual Studio, you may have to use a real MSI authoring tool for that.
Solution 5
To start it right after installation, I generate a batch file with installutil followed by sc start
It's not ideal, but it works....
Jader Dias
Perl, Javascript, C#, Go, Matlab and Python Developer
Updated on April 04, 2020Comments
-
Jader Dias about 4 years
Besides the service.StartType = ServiceStartMode.Automatic my service does not start after installation
Solution
Inserted this code on my ProjectInstaller
protected override void OnAfterInstall(System.Collections.IDictionary savedState) { base.OnAfterInstall(savedState); using (var serviceController = new ServiceController(this.serviceInstaller1.ServiceName, Environment.MachineName)) serviceController.Start(); }
Thanks to ScottTx and Francis B.
-
Matt Davis almost 15 yearsNote that this solution does not require the use of InstallUtil.exe, so you do not have to deliver it as part of your installation program.
-
Matt Davis almost 15 yearsThis is a nice solution, but still requires the use of the InstallUtil utility. If you're already delivering InstallUtil as part of your installation, this makes the most sense. But, if you want to forego packaging InstallUtil, use the command-line solution.
-
Christian.K over 14 yearsWhat's the point with the empty "catch { throw; }" clauses? Also, it is probably not a good idea to hide failures by "Rollback()" as that situation basically leaves the system in an undefined state I guess (you tryied to install a service, failed somewhere in the middle and couldn't undo it). You should at least "show" the user that there is something fishy - or does the Rollback() function write some messages to the console?
-
Matt Davis over 14 yearsThe rollback does write data to the console. As for the empty catch blocks, it's a debugging thing. I can put a breakpoint at the throw statement to examine any exceptions that may occur.
-
Christian.K over 14 yearsAh, never thought of that. Thanks.
-
Steve Reed Sr over 12 yearsVB.net code is not bad! For those of us who work in multiple languages it is nice to not have to convert the code from C!
-
avnic over 12 yearsHI, works perfect how can i pass paramter on this mathod above to OnStart(string[] args)
-
Matt Davis over 12 years
-
wmarbut over 11 yearsI get the nasty "Cannot install service from command line or debugger..." dialog using this method on a Win7 machine with .NET 4
-
Matt Davis over 11 years@wmarbut, make sure you run the command prompt as administrator on Win7.
-
wmarbut over 11 years@MattDavis It was. I also tried my dev console which works with InstallUtil.
-
Yogesh about 11 yearsI am getting error Error: The type or namespace name 'YourServiceType' could not be found (are you missing a using directive or an assembly reference?
-
tsemer almost 11 yearsNice! IsInstalled can be upgraded to
ServiceController.GetServices().Any(s => s.ServiceName == "YourServiceName");
-
bansi over 10 years
YourServiceType
is theProjectInstaller
you added to the service which containsServiceInstaller
andServiceProcessInstaller
-
programmer33 over 10 yearsIf you have an issue of 'Sub Main is declared more than once' in VB.NET (VS 2008), simply delete the sub main method from SERVICENAME.Designer.vb in your projects folder.
-
giladrv over 9 yearsI need to pass a parameter from the Main function in the above code to the service code in your first link. How would I do that?
-
Matt Davis over 9 years@giladrv, you can modify the constructor for
YourService
to accept a parameter. -
Matt Davis almost 9 years
-
Matt Davis almost 9 years@giorgi, Windows services are not started by double-clicking the executable. To start a Windows service, you can use the
sc
command from the command line or the Service console. Without the Main function, a C#-based Windows service won't even compile. -
Ali Ahmadvand over 8 yearsthank you for use full replay; when i want to start my services with your solution. first asked me to set an user name& password on "set service login" form. and after set that. raise exception on last Catch in "InstallService" method. could you tell me how to solve this problem. thanks a lot
-
Rashmin Javiya over 8 yearsVery nice. but would be good if there is UI installer available for non-tech people
-
Squirrelkiller about 8 years@Rashmin Javiya Why would any non-tech people ever manually install and even develop a windows service?
-
Rashmin Javiya about 8 years@MarlonRegenhardt What I mean is, above solution required to pass command line argument -install and -uninstall for application to understand the behavior whether to install, uninstall or simply execute service. non-technical people might not aware of these command line args.
-
Matt Davis about 8 years@RashminJaviya, that is why you wrap the commands in a higher-level installer. In our case, we use the "-install" command line argument inside an InstallShield installer. When the user uninstalls from the Add/Remove Programs console, the "-uninstall" command line argument is used. The command line arguments are merely used to make the service scriptable without requiring a dependency on InstallUtil.exe. You could accomplish the same thing wrapping the calls in two .bat files, e.g., install.bat and uninstall.bat.
-
Faizan Mubasher over 6 years@MattDavis My command line project and Service projects are separate projects. How I can add
ProjectInstaller
orYourServiceType
in my Util class? -
Charles Owen about 6 yearsThanks, this helped me to figure out how to automatically start a service.
-
AlirezaK about 5 years@Yogesh, please refer to stackoverflow.com/a/21916030/4444757 for
Your Service Type
error. -
AlirezaK about 5 years@MattDavis, Thanks a lot for the great post, I have a problem like
Ali Ahmadvand
(8 comments up) when I'd like to start my service with your solution. first asked me to set a user name & password on "set service login" form. and after the set that. raise an exception on last Catch in "InstallService" method. could you tell me how to solve this problem, please? -
Matt Davis about 5 years@Tom, in the
ServiceProcessInstaller
component, there is anAccount
property. I'm assuming that this is set toUser
in your case, which is why it's prompting for credentials. I have mine set toLocalService
, so I'm never prompted for credentials when installing my service. If you have to keep it asUser
, then you'll need to find the answer elsewhere as I'm not sure. You can read more about service account types here: docs.microsoft.com/en-us/windows/desktop/services/… -
whale70 over 4 yearsAnyone knows how it is possible to specify a service name for the new service to be created (other than just the name of the executable)?
-
Matt Davis over 4 years@whale70 See Step 4, Bullet 4 stackoverflow.com/questions/593454/…
-
whale70 over 4 years@MattDavis, I'd like to user to be able to specify the desired service name when installing the service from the command line, so configuration this name at runtime isn't a viable option for this. E.g. like: 'myapp.exe -install <serviceName>'