Hi,
I have developed a windows service (which works), however the problem I'm
having is writing to a custom event log. I have managed to create an event
source for my service and register it to my custom log (double checked this in
the registry) but I keep getting the following message appearing in the Application
log (nothing gets written to the custom log):
The description for Event ID ( 0 ) in Source ( EmailForwarder ) 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. The following information is part of the event: Email Forwarder
Service Running
To add to the above, my service is running as the LocalSystem account which
should give me full access rights. And the registry key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\SmartLogs\EmailForwarder\EventMessageFile --> is pointing to
EventLogMessages.dll.
Any help will be much appreciated!!
Thanks.

Problem writing to a custom event log
llively
System.Diagnostics.EventLog.DeleteEventSource("Smart EmailForwarder"); //I do this because an event source is automatically created in the Application Log by default
if (!System.Diagnostics.EventLog.SourceExists("Smart EmailForwarder"))
{
System.Diagnostics.EventLog.CreateEventSource("Smart EmailForwarder",
"SmartLogs");
Specify the event log to use your service application as source
}
SmartLog.Source = "Smart EmailForwarder";
2. Method call to write to the custom event log:
WriteToEventLog("Smart Email Forwarder Service Stopped", EventLogEntryType.Information);
3. Method used to write to custom log:
public void WriteToEventLog(string sEventLogEntry, EventLogEntryType EventType)
{
SmartLog.WriteEntry(sEventLogEntry, EventType);
}
NicS
Could you post the code you are using to write to the event log I believe the problem lies in the fact that you are calling an overload that is assuming that you are passing it a message ID rather than a string message so it can't find the message resource and is generating the above error.
Michael Taylor - 10/23/06
Steve Hempen
Your code worked fine for me. You might have some legacy information installed from a previous run. Use the registry editor to clean up any event sources and logs and then try reinstalling your service (you might have to reboot if you deleted any registry keys).
The event sources are HKLM\System\CurrentControlSet\EventLog.
Michael Taylor - 11/9/06
MS_ISV
I've tried everything recommended here, but I'm still getting the same errors logged to the Application log. If I don't attempt to use a custom log, then everything works fine. As soon as I try to associate my source to a custom log, I get errors.
I set the Log property of the EventLogInstaller within the ServiceInstaller class. I then also set the Log property of the EventLog in my ServiceBase class. Still doesn't work. I tried deleting the source and recreating it. Doesn't work. I have no idea what else to do.... any help would be greatly appreciated.
-Mark-
Oliviero_83
However, it's now logging messages twice, which I need to track down. In any case, thanks for your help!
-Mark-
dsani
Can you post your code from your service and from the installer so we can take a look at it
Michael Taylor - 11/9/06
glok
I see. Your service name is Smart EmailForwarder so when the service installs it automatically creates the source and the association to the Application log. You want to redirect it to a custom log. The problem is that you are trying to delete the default source and use a new source/log instead.
The issue becomes how to map the source to a new log. You should do this during installation. The problem is that the service installer will create the necessary event log installer logic automatically. Therefore you need to force a change in the log name after the installer is created but before it is installed. Reflection would work here but there is an easier way.
Within ServiceInstaller is the EventLogInstaller that is used to create the event source/log. The problem is that it is private. However in order for the installer to work properly it must be added to the list of installers. It is added as a child of ServiceInstaller. ServiceInstaller itself is a child installer of ServiceProcessInstaller. Therefore you can write a function to enumerate the installers that will be run and find the event log. You can then modify the log it will write to. Here is some sample code to get you started.
public
ProjectInstaller(){
InitializeComponent();
EventLogInstaller inst = FindEventLogInstaller(this.Installers);
if (inst != null)
{
inst.Log = "CustomLog";
};
} private EventLogInstaller FindEventLogInstaller(InstallerCollection installers)
{
foreach (Installer inst in installers)
{
if (inst is EventLogInstaller)
return (EventLogInstaller)inst;
if (inst.Installers != null)
{
EventLogInstaller instLog = FindEventLogInstaller(inst.Installers);
if (instLog != null)
return instLog;
};
};
return null;
}
Remove all the event source delete/create stuff from your constructor and simply use the EventLog property provided by the base class.
public
Service1(){
InitializeComponent();
EventLog.Log = "CustomLog";
EventLog.WriteEntry("Testing", EventLogEntryType.Information);
}
It would have been nice if MS had exposed an option off of ServiceInstaller to set the log name like they did for the source but alas they didn't. The class is not sealed so you can actually write an enhanced version that does this for you. The only issue is the fact that the event log installer is still hidden. Therefore you'll still have to enumerate the child installers of the service installer but it'll be quicker. Here is some sample code.
private EventLogInstaller m_installerLog;public class ServiceInstallerEx : ServiceInstaller
{
public string LogName
{
get { return LogInstaller.Log; }
set { LogInstaller.Log = value; }
}
private EventLogInstaller LogInstaller
{
get
{
if (m_installerLog == null)
{
foreach (Installer inst in Installers)
{
if (inst is EventLogInstaller)
{
m_installerLog = (EventLogInstaller)inst;
break;
};
};
};
return m_installerLog;
}
}
}
Now you don't have to modify the ServiceProcessInstaller code at all other than to use ServiceInstallerEx rather than ServiceInstaller. You can then use the property window to set the custom log option. You'll still need to point the service's EventLog property to your custom log but other than that it works as expected.
Michael Taylor - 10/25/06
pavvu_kk
Here's the code for the installer class:
[RunInstallerAttribute(true)]
public class InstallerInfo : Installer
{
private ServiceInstaller serviceInstaller;
private ServiceProcessInstaller processInstaller;
private EventLogInstaller logInstaller;
public InstallerInfo()
{
// Instantiate installers for process and services.
processInstaller = new ServiceProcessInstaller();
serviceInstaller = new ServiceInstaller();
// The services are started manually.
serviceInstaller.StartType = ServiceStartMode.Manual;
serviceInstaller.ServiceName = "SunGard Agent";
logInstaller = FindLogInstaller( serviceInstaller.Installers );
if( logInstaller != null )
logInstaller.Log = "SunGardEXP";
Installers.Add( serviceInstaller );
Installers.Add( processInstaller );
}
EventLogInstaller FindLogInstaller( InstallerCollection installers )
{
foreach( Installer installer in installers )
{
if( installer is EventLogInstaller )
return (EventLogInstaller)installer;
}
return null;
}
public string ServiceName
{
get { return serviceInstaller.ServiceName; }
set
{
serviceInstaller.ServiceName = value;
logInstaller.Source = value;
}
}
}
The name of the service gets changed to "Agent_fw5" before the installers are run.
In the constructor of my service class, I had the following line:
this.EventLog.Log = "SunGardEXP";
And to do the logging, I do the following (no need to know what the various parameters to the String.Format are):
eventLog.WriteEntry( String.Format( "[{0}] {1}: {2}", level.ToString(), context.ToString(), message.ToString() ), type );
I also tried the example code on this page: http://quickstart.developerfusion.co.uk/QuickStart/howto/doc/LogWrite.aspx
Using the line (based on code compiled from the above page):
LogWriter SunGardEXP "Test" "Agent_fw5"
it works fine before the service is installed. Once the service is installed, logging simple doesn't work for that source anymore.
-Mark-
Noral
Hi All,
This installer thing helped me too get rid of the complex event viewer related problems..... But like mark said I was also finding 2 messages in event viewer..........
The solution is to set
this.AutoLog = false;
AutoLog is a property of Servicebase class
This will solve all problems on versions like 2k3, xp etc if you have followed method suggested by taylor, so that OS does not interfere with your writing of messages into event viewer.
cedubose
In the project installer for the Service, in ServiceInstaller override the OnAfterInstall subroutine.
Add a line to create a new event source, and then write an entry to it.
The source and log will be created.
Here is the code which was added:
Protected Overrides Sub OnAfterInstall(ByVal savedState As System.Collections.IDictionary)
MyBase.OnAfterInstall(savedState)
If Not EventLog.SourceExists("NewSourceName") Then
EventLog.CreateEventSource("NewSourceName", "LogName")
End If
EventLog.WriteEntry("NewSourceName", "NewSourceName Service Installed")
End Sub
Protected Overrides Sub OnAfterInstall(ByVal savedState As System.Collections.IDictionary)
MyBase.OnAfterInstall(savedState)
If EventLog.SourceExists("NewSourceName") Then
EventLog.DeleteEventSource("NewSourceName")
End If
EventLog.CreateEventSource("NewSourceName", "LogName")
EventLog.WriteEntry("NewSourceName", "NewSourceName Service Installed")
End Sub