Creating a Windows Service with C#, concluded
(Page 1 of 4 )
Welcome back to our series on developing a Windows Service with C#. So far we have created a rudimentary TCP server and installed it as a Windows Service. In this final installment we are going to add some simple event logging to our service and create a simple service controller application that can be minimized to the system tray.
The Zip file containing the source code for this and the other parts of this series can be found HERE.
The Last Leg
We will be using a class from vbAccelerator.com, found here: http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects/SysTray/
SysTray_Code_zip_SysTrayTester_SysTray_cs.asp, to interact with the system tray. The reason I use this class is that the .NET Framework does not expose any access to the system tray; we have to import Win32 API functions from various DLL files. The class from vbAccelerator.com handles all this and more-–it provides a balloon tooltip mechanism as an added bonus.
Event Logging
Using the Windows event log is a breeze with .NET. Using the System.Diagnostics namespace, which is already referenced in our TimeServerService class, we have access to the EventLog class. Before we actually code up any event logging, let’s at least make it configurable so that logging can be turned off without recompiling. We should also make the name of the custom log configurable.
Right click on the TimeService project, select “Add”, “Add New Item”, “Application Configuration”. Leave the default name “App.config”. Open the App.config file and add a new node under configuration called “appSettings”. We will add two keys to the Application Settings section, “LoggingEnabled” and “LogName”. Your App.config file should look like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="LoggingEnabled" value="true" />
<add key="LogName" value="Time Service" />
</appSettings>
</configuration>
You can change the value of LogName to whatever you want. We will write our code so that any value other than “true” means that the logging functionality of the service is turned off. To use these settings, add a reference to the System.Configuration namespace to TimeServerService.cs:
using System.Configuration;
Now we need to add a few properties and methods to our class. Since every time we need to add a message we have to check the LoggingEnabled setting, we will create a helper method in the TimeServerService class to handle writing the log entries. Add the following properties:
private bool loggingEnabled;
private string logName;
private EventLog log;
Initialize these fields in the constructor, like so:
public TimeServerService()
{
InitializeComponent();
this.listener = new TcpListener(ip, port);
this.logName = ConfigurationSettings.AppSettings
["LogName"];
if (ConfigurationSettings.AppSettings["LoggingEnabled"]
== "true")
this.loggingEnabled = true;
else
this.loggingEnabled = false;
if (this.loggingEnabled)
{
if (!EventLog.SourceExists(this.logName))
EventLog.CreateEventSource(this.ServiceName,
this.logName);
this.log = new EventLog();
this.log.Source = this.logName;
}
}
The code above grabs our configuration settings and initializes the class's new fields accordingly. Next we need to create our helper method, or methods, to actually write the entries to the log. The EventLog.WriteEntry() method signature we will use accepts a string message and an EventLogEntryType type, and so will our helper method. We will create an overloaded version of our helper method that takes just an exception and one that takes just a string, defaulting to EventLogEntryType.Error and EventLogEntryType.Information, respectively. The methods are short and simple:
private void Log(string message, EventLogEntryType type)
{
if (this.loggingEnabled)
this.log.WriteEntry(message, type);
}
private void Log(string message)
{
this.Log(message, EventLogEntryType.Information);
}
private void Log(Exception e)
{
this.Log(e.Message + "\n" + e.StackTrace,
EventLogEntryType.Error);
}
Now we can simply call Log(message) for general information messages and Log(exception) to log errors. The Log(message, type) version can be used for other types of messages such as warnings and audits if you decide to use those types later. Note that in the Log(message, type) method, we check to see if logging is enabled before writing anything to the event log.
Next: Logging events >>
More C# Articles
More By David Fells