Alex Rivera | Logout

What is the most reliable way to create a custom event log and event source during the installation of a .Net Service

Asked 2008-09-22T15:23:57.307
25

I am having difficulty reliably creating / removing event sources during the installation of my .Net Windows Service.

Here is the code from my ProjectInstaller class:

// Create Process Installer
ServiceProcessInstaller spi = new ServiceProcessInstaller();
spi.Account = ServiceAccount.LocalSystem;

// Create Service
ServiceInstaller si = new ServiceInstaller();
si.ServiceName = Facade.GetServiceName();
si.Description = "Processes ...";
si.DisplayName = "Auto Checkout";
si.StartType = ServiceStartMode.Automatic;

// Remove Event Source if already there
if (EventLog.SourceExists("AutoCheckout"))
    EventLog.DeleteEventSource("AutoCheckout");

// Create Event Source and Event Log     
EventLogInstaller log = new EventLogInstaller();
log.Source = "AutoCheckout";
log.Log = "AutoCheckoutLog";

Installers.AddRange(new Installer[] { spi, si, log });

The facade methods referenced just return the strings for the name of the log, service, etc.

This code works most of the time, but recently after installing I started getting my log entries showing up in the Application Log instead of the custom log. And the following errors are in the log as well:

The description for Event ID ( 0 ) in Source ( AutoCheckout ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details.

For some reason it either isn't properly removing the source during the uninstall or it isn't creating it during the install.

Any help with best practices here is appreciated.

Thanks!

In addition, here is a sample of how I am writing exceptions to the log:

// Write to Log
EventLog.WriteEntry(Facade.GetEventLogSource(), errorDetails, EventLogEntryType.Error, 99);

Edit
Report

4 Answers

27

The ServiceInstaller class automatically creates an EventLogInstaller and puts it inside its own Installers collection.

Try this code:

ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller();
serviceProcessInstaller.Password = null;
serviceProcessInstaller.Username = null;
serviceProcessInstaller.Account = ServiceAccount.LocalSystem;

// serviceInstaller
ServiceInstaller serviceInstaller = new ServiceInstaller();
serviceInstaller.ServiceName = "MyService";
serviceInstaller.DisplayName = "My Service";
serviceInstaller.StartType = ServiceStartMode.Automatic;
serviceInstaller.Description = "My Service Description";
// kill the default event log installer
serviceInstaller.Installers.Clear(); 

// Create Event Source and Event Log     
EventLogInstaller logInstaller = new EventLogInstaller();
logInstaller.Source = "MyService"; // use same as ServiceName
logInstaller.Log = "MyLog";

// Add all installers
this.Installers.AddRange(new Installer[] {
   serviceProcessInstaller, serviceInstaller, logInstaller
});
answered 2009-08-17T10:59:49.320
8

Couple of things here

Creating Event Logs and Sources on the fly is pretty frowned upon. primarily because of the rights required to perform the action - you don't really want to bless your applications with that power.

Moreover if you delete an event log or source the entry is only truely deleted when the server reboots, so you can get into wierd states if you delete and recreate entries without bouncing the box. There are also a bunch of unwritten rules about naming conflicts due to the way the metadata is stored in the registry.

The recommended path is an installer script and installutil, or a Windows Setup routine.

answered 2008-09-22T17:22:57.163
3

I also followed helb's suggestion, except that I basically used the standard designer generated classes (the default objects "ServiceProcessInstaller1" and "ServiceInstaller1"). I decided to post this since it is a slightly simpler version; and also because I am working in VB and people sometimes like to see the VB-way.

As tartheode said, you should not modify the designer-generated ProjectInstaller class in the ProjectInstaller.Designer.vb file, but you can modify the code in the ProjectInstaller.vb file. After creating a normal ProjectInstaller (using the standard 'Add Installer' mechanism), the only change I made was in the New() of the ProjectInstaller class. After the normal "InitializeComponent()" call, I inserted this code:

  ' remove the default event log installer 
  Me.ServiceInstaller1.Installers.Clear()

  ' Create an EventLogInstaller, and set the Event Source and Event Log      
  Dim logInstaller As New EventLogInstaller
  logInstaller.Source = "MyServiceName"
  logInstaller.Log = "MyCustomEventLogName"

  ' Add the event log installer
  Me.ServiceInstaller1.Installers.Add(logInstaller)

This worked as expected, in that the installer did not create the Event Source in the Application log, but rather created in the new custom log file.

However, I had screwed around enough that I had a bit of a mess on one server. The problem with the custom logs is that if the event source name exists associated to the wrong log file (e.g. the 'Application' log instead of your new custom log), then the source name must first be deleted; then the machine rebooted; then the source can be created with association to the correct log. The Microsoft Help clearly states (in the EventLogInstaller class

answered 2010-09-09T08:03:43.427
0

Following helb's suggestion resolved the problem for me. Killing the default event log installer, at the point indicated in his example, prevented the installer from automatically registering my Windows Service under the Application Event log.

Far too much time was lost attempting to resolve this frustrating quirk. Thanks a million!

FWIW, I could not modify the code within my designer-generated ProjectInstaller class without causing VS to carp about the mods. I scrapped the designer-generated code and manually entered the class.

answered 2009-09-10T20:55:04.843

Your Answer