In Part 2 we discussed how to add an installer for the Windows Service we wrote in Part 1. Today, we'll learn how we can tell the Installer to start our service after it has been installed.
This article is one in a five-part series covering the following topics:
- Programming a Windows Service in C#
- Adding an Installer for Your Windows Service
- Getting Your Installer to Start Your Service
- Some Options for Debugging Your Windows Services
- Adding an Uninstaller for Your Windows Service
The examples in this series are written in C#, but this should help anyone out there wanting to do this on the .NET 2.0 Framework no matter if they're using C#, VB.Net, or any other language. Additionally, the code in this article can be used in any context to start a Windows Service programmatically - not just from an installer.
If you're just jumping in at this article in the series, we've already written our service and added an installer to it. If you'd like a copy of our sample code up until this point (instead of having to go through steps 1 & 2 to recreate it), you can
download it here.
On to the code!
Getting Your Installer to Start Your Service
You may have notice that when the installer installs your Windows Service, it doesn't start it automatically, even if the StartType for the service is set to Automatic. Today, we'll learn how we can tell the Installer to start our service after it has been installed.
1. Add the System.ServiceProcess Namespace.We'll be using the
System.ServiceProcess.ServiceController class for this portion of the project, so be sure to add a
using statement for
System.ServiceProcess to the top of your code:
using System.ServiceProcess;
2. Add an Override for the Install function.Go into Code View of your Project Installer class (ProjectInstaller.cs in our example.) Add an override for the Install function to your class. All you have to type is "
public override void Inst" and hit tab, and Visual Studio's auto-complete should add the class for you, complete with the
base.Install line seen below.
Here is the complete code for my example class, with the new bits
highlighted:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
namespace SuperService
{
[RunInstaller(true)]
public partial class ProjectInstaller : Installer
{
public ProjectInstaller()
{
InitializeComponent();
}
public override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
}
}
}
3. Start your Service using the ServiceController.Since we want our Windows Service to start
after the install has finished (we can't exactly start it before it's installed!) we'll add our code to start the service
after our
base.Install is called. (Note: Optionally, you could have instead done this by adding an event handler for
this.AfterInstall and putting your code there. As far as I know, it doesn't make any major difference which way you do it.)
public override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
ServiceController controller = new ServiceController("Logger");
controller.Start();
}
Let's break this down for ya'. As I mentioned before, we add our code to start our service
after the
base.Install line.
We start by instantiating a new
ServiceController object, passing the name of our Windows Service as the only parameter. We specified this name earlier in the
ServiceName property of our
ServiceInstaller object. (Go to Design View of your Project Installer class and click on serviceInstaller1 to view this property.) If this name doesn't match your
ServiceName property, you'll get an error (or possibly start the wrong service!)
Finally, we run the Start function of our ServiceController to start our service up. That's about it. You might want to add some code to handle any errors this step may throw so your install doesn't fail if your service fails to start. For example, the code below will trap the error and record it to the event log. If you use it, remember to also add a reference to the
System.Diagnostics namespace to the top of your code.
public override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
ServiceController controller = new ServiceController("Logger");
try
{
controller.Start();
}
catch (Exception ex)
{
String source = "SuperService Installer";
String log = "Application";
if (!EventLog.SourceExists(source))
{
EventLog.CreateEventSource(source, log);
}
EventLog eLog = new EventLog();
eLog.Source = source;
eLog.WriteEntry(@"The service could not be started. Please start the service manually. Error: " + ex.Message, EventLogEntryType.Error);
}
}
That's all there is to it! Next time, join us to learn a few of your options for debugging your newly-installed service. Until then, feel free to check out some of these other great articles that I used as sources for this series:
Labels: Coding