Create a .NET Windows Service in 5 steps with Topshelf
Topshelf is an open-source hosting framework for building Windows Services using .NET. With Topshelf you can create in a few lines of code your own windows service. It's a kind of internal DSL for building windows services. I used version 2.2 of Topshelf and the binaries and sources can be found here (GitHub).
First download Topshelf from GitHub, I used version 2.2 (direct link).
- Create a console application named
SampleWindowsService
inside Visual Studio - Be sure to change the target framework to .NET Framework 4 - Reference the binaries
TopShelf.dll
andlog4net.dll
(included in Topshelf). -
Create a simple service called 'SampleService' that simply write every 5 seconds to the log. Note that we create explicit a
Start
andStop
method which is conceptually the minimum that a windows service need.public class SampleService { private Timer _timer = null; readonly ILog _log = LogManager.GetLogger( typeof(SampleService)); public SampleService() { double interval = 5000; _timer = new Timer(interval); _timer.Elapsed += new ElapsedEventHandler(OnTick); } protected virtual void OnTick(object sender, ElapsedEventArgs e) { _log.Debug("Tick:" + DateTime.Now.ToLongTimeString()); } public void Start() { _log.Info("SampleService is Started"); _timer.AutoReset = true; _timer.Enabled = true; _timer.Start(); } public void Stop() { _log.Info("SampleService is Stopped"); _timer.AutoReset = false; _timer.Enabled = false; } }
-
In the main method of our console application we will use Topshelf to host our SampleService. We we are telling Topshelf how to start and stop the service, what the service name is, etc. Note that we need to configure log4net for Topshelf and our service!
static void Main(string[] args) { XmlConfigurator.ConfigureAndWatch( new FileInfo(".\log4net.config")); var host = HostFactory.New(x => { x.EnableDashboard(); x.Service(s => { s.SetServiceName("SampleService"); s.ConstructUsing(name => new SampleService()); s.WhenStarted(tc => { XmlConfigurator.ConfigureAndWatch( new FileInfo(".\log4net.config")); tc.Start(); }); s.WhenStopped(tc => tc.Stop()); }); x.RunAsLocalSystem(); x.SetDescription("SampleService Description"); x.SetDisplayName("SampleService"); x.SetServiceName("SampleService"); }); host.Run(); }
-
The only thing we have to do now is to configure log4net. Create a file called
log4net.config
with the following configuration.log4net.config<?xml version="1.0" encoding="utf-8" ?> <log4net> <appender name="main" type="log4net.Appender.ConsoleAppender"> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%-5level - %message%newline" /> </layout> </appender> <appender name="udp" type="log4net.Appender.UdpAppender"> <RemoteAddress value="log4view-local"/> <RemotePort value="7071"/> <layout type="log4net.Layout.XmlLayoutSchemaLog4j"/> </appender> <root> <level value="DEBUG" /> <appender-ref ref="main" /> <appender-ref ref="udp" /> </root> </log4net>
This configuration enables to output to the console and through a UDP network protocol so that we can easily monitor the log statements when installed as a windows service. I used Log2Console (Codeplex) to monitor my log statements through UDP.
Note
Make sure the output directory of
log4net.config
is set toCopy always
Note
Note that there is an issue with log4net related to IPv6 and Windows Vista/7. You can fix it by adding the following
127.0.0.1 log4view-local
to your hosts file which can be found in folderC:\Windows\System32\drivers\etc\hosts
.
When you fit F5 you will see that Topshelf outputs some log statements and you will see that the log statements of our SampleService is included and everything is working properly.
In order to install SampleService as a Windows Service you simply need to do the following through the command prompt.
Warning
Be sure to launch the command prompt as an administrator!
After that when the windows service has been installed successfully we can start the service through services.msc or simply by typing
Now we can open Log2Console to monitor our log files that is send through the UDP appender.
To uninstall the service we simply write
The sources can be found here (BitBucket)