While working on a Windows Service project in .net (Visual Studio 2008), a minor problem related to defining custom event logs kept bugging me.
As you already know, to debug your Windows Service you should use InstallUtil tool to install the service in your Windows. For InstallUtil to be able to install your Service, you add an Installer to your project which contains a ServiceProcessInstaller and a ServiceInstaller. So far everything is cool. You set the properties on these components and BAM! you can now easily install your Service. If you look closely at the IinstallUtil messages on your screen you will see that it creates an EventLog source with the same name you specify for the Service Name property of the ServiceInstaller component and assigns that source to a standard Windows event log called Application.
According to MSDN, "Applications and services should write to the Application log or a custom log. Device drivers should write to the System log.". I wanted to create a separate log for my Windows Service and not use the Windows Application log. There may be multiple ways to do this but the suggested approach is to create the Event Source and related Log during the installation of your application. In case of a Windows Service, ServiceInstaller is designed to do this for you by creating an event source for your Windows Service and assigning it to the Application log.
But what if you want to use a log other than Application log? that's easy too. You can check for the event source each time your Service is instantiated and if it does not exist, create the source and the log, similar to what is suggested here, or use EventLogInstaller class to create the log and the source at the time your service is being installed. The second approach seems to be more appropriate because it creates the log at installation time and removes it when you uninstall the service.
So I went ahead and used the EventLogInstaller class:
namespace MyService
{
[RunInstaller(true)]
public partial class CustomEventLogInstaller : Installer
{
private EventLogInstaller customEventLogInstaller;
public CustomEventLogInstaller()
{
InitializeComponent();
customEventLogInstaller = new EventLogInstaller();
customEventLogInstaller.Source = "My Service";
customEventLogInstaller.Log = "My Service Events";
Installers.Add(customEventLogInstaller);
}
public static void Main()
{
}
}
}
Interestingly, ServiceInstaller was still creating its default source and assigning it to the Application log before my EventLogInstaller creates the source and installation would fail because the Event Source already existed. I could just use a different name for my event source and let ServiceInstaller create its own source, but the idea kept bugging me. So I decided to prevent the ServiceInstaller from creating its default source.
After spending a good deal of time, I finally got it working the way i wanted it. The trick is to find the unwanted instance of the EventLogInstaller in the Installers property of the ServiceInstaller and remove it. This must be done in the constructor method of the ProjectInstaller:
namespace MyService
{
[RunInstaller(true)]
public partial class ProjectInstaller : Installer
{
public ProjectInstaller()
{
InitializeComponent();
// Remove the default Event Log Installer
EventLogInstaller DefaultInstaller = null;
foreach (Installer installer in serviceInstaller1.Installers)
{
if (installer is EventLogInstaller)
{
DefaultInstaller = (EventLogInstaller)installer;
break;
}
}
if (DefaultInstaller != null)
{
serviceInstaller1.Installers.Remove(DefaultInstaller);
}
}
}
}
f28e5e07-d968-4f0f-aa71-91d5b9d93e8f|0|.0|96d5b379-7e1d-4dac-a6ba-1e50db561b04