EventLog Properties related - c#

How to write C#.NET code for Log Size groupbox(in Properties window,Application eventlog,Eventviewer in WIndows XP OS) in EventViewer - Eventlog Properties.
Please provide me the code for the same.

I think what sukumar is asking is how can he programatically change the size of an event log in C#?
// Get the Event Log
this.eventLog = new EventLog();
this.eventLog.Source = "Your.Log.Source";
// Configure the Event Log
// Set the log size
this.eventLog.MaximumKilobytes = 5120;
// Ower-write old records when log becomes full
this.eventLog.ModifyOverflowPolicy(OverflowAction.OverwriteAsNeeded, 0);
// Add the trace listner
Trace.Listeners.Add(new EventLogTraceListener(this.eventLog));
If you righ-click on an event log (eg the Application Log), and select properties. You will see there is a log size that you can set.
The problem is say you have a custom log that you are writing to. The overflow action is set to DoNotOverwrite (by default), if you don't change it to OverwriteAsNeeded, you will throw an exception when the log becomes full. System logs seem to have OverwriteOlder as a default.
Increasing the log size just gives you a bigger history...

Related

Why does new custom event log returned by EventLog.GetEventLogs contain Application log entries?

I have a very strange issue that doesn't seem to correspond to any of the documentation I'm reading about EventLog.GetEventLogs.
I created a new custom log using Powershell (a very straightforward operation) which contains zero entries. However, when I call EventLog.GetEventLogs and locate the new log in the resulting array, the Entries property contains all of the Application log entries. I was expecting the number of entries to be zero, which is what I see in the event viewer.
What could cause this result?
PowerConsole:
> New-EventLog
> Log Name? MyModule
> Souce Name 1? MyModule
> Source Name 2?
C# Code:
var logs = EventLog.GetEventLogs();
var log = logs.FirstOrDefault(l => l.Log == "MyModule");
Response.Write(log.Entries.Count); // Outputs 18,896
I think you may be looking at the wrong method.
Rather than calling GetEventLogs, get a reference to your custom log, and then look at it's entries:
EventLog myLog = new EventLog("my_log");
var count = myLog.Entries.Count;
If we then write an entry like this:
EventLog myLog = new EventLog("my_log");
myLog.Source = "my_source";
myLog.WriteEntry("A test entry");
The count will increase as expected.
I found a solution. The PowerShell command that creates new logs ultimately modifies the registry. I'm guessing that some of those registry settings don't get applied until some other command is executed. After restarting my machine, EventLog.GetEvenLogs produced the expected results.

Writing Events to Specific EventViewer

I have read multiple articles and SO questions on the Windows Event Viewer. However, I am still unable to accomplish my goal. I have a Windows Service that I'll call "Social". I want to write information from this Windows Service to the Windows Event Viewer. At this time, I'm trying the following:
var message = "Test Log";
using (var sw = File.AppendText(AppDomain.CurrentDomain.BaseDirectory + "test.txt"))
{
sw.WriteLine(message);
}
var eventLog = new EventLog();
eventLog.Source = "Service";
eventLog.Log = "Social";
eventLog.BeginInit();
if (EventLog.SourceExists(eventLog.Source) == false)
{
EventLog.CreateEventSource(eventLog.Source, "Social");
}
eventLog.EndInit();
eventLog.WriteEntry(message, EventLogEntryType.Information);
I added the "test.txt" file just to ensure my code was being reached. That code runs fine. However, I never see my message written in the Event Viewer. In fact, I never see a new Event source get created. I was expecting to go to the Windows Event Viewer and see a new item located at "Event Viewer -> Applications and Services Logs -> Social Media Analyzer". However, I do not see that anywere.
Notably, the "Social" log exists in the event viewer. However, nothing gets written to it. The logs get written to the "Application" log instead. It's almost like the Windows Service is ignoring the fact that I want to write to a specific log.
What am I doing wrong?
eventLog.Log = "Application";
...
EventLog.CreateEventSource(eventLog.Source, "Application");
You're writing your events to the Application Log under "Windows Logs". The events should specify the Source (column) as being "Social Media Analyzer".
If you want to write to a custom log you need something like
EventLog.CreateEventSource("MyEventSource", "Social Media Analyzer");

Can not re-register event source to new custom event log

I have created an event log source using:
if (!EventLog.SourceExists(EventLogSource)) EventLog.CreateEventSource(EventLogSource);
So every log entry that uses EventLogSource goes into "Application". Then I wanted that all entries those use EventLogSource go into another custom log; so I deleted them then created source with new custom log:
try { EventLog.DeleteEventSource(EventLogSource); }
catch { }
try { EventLog.Delete(EventLogName); }
catch { }
...
if (!EventLog.SourceExists(EventLogSource)) EventLog.CreateEventSource(EventLogSource, EventLogName);
while (!EventLog.SourceExists(EventLogSource)) { }
BUT when I log using EventLogSource the entries still are going into "Application" instead of EventLogName.
Note:
I wrote this in comments and I think It helps to describe my problem better:
In Windows Event Viewer you see a "Windows Logs" and "Application" is under that. There is another node in the tree named "Applications and Services Logs" which I want to create a custom log under that. I can do that successfully. The problem is that an event source that was previously registered to "Application" can not be un-registered from "Application" and re-register in my own "MyCustomLog".
The event system in Windows caches some information about sources. This means that if you delete a source and re-add it, it will continue to be logged to the same log it was using originally.
There's no documented way to force the event system to clear this cache. The only way I know of is to reboot the machine - so you need to delete the source, reboot, then re-create the source.

EventLog.CreateEventSource is not creating a custom log

I have some code like this:
EventLog.CreateEventSource("myApp", "myAppLog");
EventLog.WriteEntry("myApp", "Test log message", EventLogEntryType.Error);
Now, unless I'm missing something having read MSDN, this should cause a new log 'myAppLog' to be created in the event viewer, and an entry should be added to that new log with the source name 'myApp'. But, I can't get the new log to be created. This always just writes an error log message to the Application log, with the source 'myApp' - 'myAppLog' is nowhere to be seen. What am I doing wrong? I am logged in as an Administrator.
Is it possible that you already used the source "myApp" when writing to the standard Application log? If so according to MSDN:
If a source has already been mapped to
a log and you remap it to a new log,
you must restart the computer for the
changes to take effect.
http://msdn.microsoft.com/en-us/library/2awhba7a.aspx
(about half way down the page)
I have just written a little code to help me out of this. source registered in another log issue which I have encountered and don't want to manually have to remove sources from logs. What I decided to do was check if the source exists, if it does check that its linked to the correct log, if it isn't delete the source, now that it doesn't exist or f it never did create the Log brand new.
protected const string EventLogName = "MyLog";
private static bool CheckSourceExists(string source) {
if (EventLog.SourceExists(source)) {
EventLog evLog = new EventLog {Source = source};
if (evLog.Log != EventLogName) {
EventLog.DeleteEventSource(source);
}
}
if (!EventLog.SourceExists(source)) {
EventLog.CreateEventSource(source, EventLogName);
EventLog.WriteEntry(source, String.Format("Event Log Created '{0}'/'{1}'", EventLogName, source), EventLogEntryType.Information);
}
return EventLog.SourceExists(source);
}
public static void WriteEventToMyLog(string source, string text, EventLogEntryType type) {
if (CheckSourceExists(source)) {
EventLog.WriteEntry(source, text, type);
}
}
Hopefully it helps :)
You might be forgetting to set the Source property on your EventLog.
It should look something like this:
if(!EventLog.SourceExists("MySource"))
{
EventLog.CreateEventSource("MySource", "MyNewLog");
}
EventLog myLog = new EventLog();
myLog.Source = "MySource";
myLog.WriteEntry("Writing to event log.");
Here's the MSDN article for reference.
Did you set the source on your EventLog?
From MSDN Article.
You must set the Source property on your EventLog component instance before you can write entries to a log. When your component writes an entry, the system automatically checks to see if the source you specified is registered with the event log to which the component is writing, and calls CreateEventSource if needed. In general, create the new event source during the installation of your application. This allows time for the operating system to refresh its list of registered event sources and their configuration. If the operating system has not refreshed its list of event sources and you attempt to write an event with the new source, the write operation will fail. If creating the source during installation is not an option, then try to create the source well ahead of the first write operation, perhaps during your application initialization. If you choose this approach, be sure your initialization code is running with administrator rights on the computer. These rights are required for creating new event sources.
If you have checked all suggestions in other answers, then read the following
From MSDN
The operating system stores event logs as files. When you use EventLogInstaller or CreateEventSource to create a new event log, the associated file is stored in the %SystemRoot%\System32\Config directory on the specified computer. The file name is set by appending the first 8 characters of the Log property with the ".evt" file name extension.
Make sure that the first 8 characters are unique.
Basically, the simplest solution is you have to close your visual studio and run as administrator mode. Then, you would be able to resolve this error

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

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);
Regarding stephbu's answer: The recommended path is an installer script and installutil, or a Windows Setup routine.
I am using a Setup Project, which performs the installation of the service and sets up the log. Whether I use the installutil.exe or the windows setup project I believe they both call the same ProjectInstaller class I show above.
I see how the state of my test machine could be causing the error if the log isn't truly removed until rebooting. I will experiment more to see if that solves the issue.
Edit:
I'm interested in a sure fire way to register the source and the log name during the installation of the service. So if the service had previously been installed, it would remove the source, or reuse the source during subsequent installations.
I haven't yet had an opportunity to learn WiX to try that route.
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
});
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.
The best recommendation would be to not use the Setup Project in Visual Studio. It has very severe limitations.
I had very good results with WiX
I have to agree with stephbu about the "weird states" that the event log gets into, I've run into that before. If I were to guess, some of your difficulties lie there.
However, the best way that I know of to do event logging in the application is actually with a TraceListener. You can configure them via the service's app.config:
http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlogtracelistener.aspx
There is a section near the middle of that page that describes how to use the EventLog property to specify the EventLog you wish to write to.
Hope that helps.
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 description):
The Install method throws an exception
if the Source property matches a
source name that is registered for a
different event log on the computer.
Therefore, I also have this function in my service, which is called when the service starts:
Private Function EventLogSourceNameExists() As Boolean
'ensures that the EventSource name exists, and that it is associated to the correct Log
Dim EventLog_SourceName As String = Utility.RetrieveAppSetting("EventLog_SourceName")
Dim EventLog_LogName As String = Utility.RetrieveAppSetting("EventLog_LogName")
Dim SourceExists As Boolean = EventLog.SourceExists(EventLog_SourceName)
If Not SourceExists Then
' Create the source, if it does not already exist.
' An event log source should not be created and immediately used.
' There is a latency time to enable the source, it should be created
' prior to executing the application that uses the source.
'So pass back a False to cause the service to terminate. User will have
'to re-start the application to make it work. This ought to happen only once on the
'machine on which the service is newly installed
EventLog.CreateEventSource(EventLog_SourceName, EventLog_LogName) 'create as a source for the SMRT event log
Else
'make sure the source is associated with the log file that we want
Dim el As New EventLog
el.Source = EventLog_SourceName
If el.Log <> EventLog_LogName Then
el.WriteEntry(String.Format("About to delete this source '{0}' from this log '{1}'. You may have to kill the service using Task Manageer. Then please reboot the computer; then restart the service two times more to ensure that this event source is created in the log {2}.", _
EventLog_SourceName, el.Log, EventLog_LogName))
EventLog.DeleteEventSource(EventLog_SourceName)
SourceExists = False 'force a close of service
End If
End If
Return SourceExists
End Function
If the function returns False, the service startup code simply stops the service. This function pretty much ensures that you will eventually get the correct Event Source name associated to the correct Event Log file. You may have to reboot the machine once; and you may have to try starting the service more than once.
I am having the same problems. In my case it seems that Windows installer is adding the event source which is of the same name as my service automatically and this seems to cause problems. Are you using the same name for the windows service and for the log source? Try changing it so that your event log source is called differently then the name of the service.
I just posted a solution to this over on MSDN forums which was to that I managed to get around this using a standard setup MSI project. What I did was to add code to the PreInstall and Committed events which meant I could keep everything else exactly as it was:
SortedList<string, string> eventSources = new SortedList<string, string>();
private void serviceProcessInstaller_BeforeInstall(object sender, InstallEventArgs e)
{
RemoveServiceEventLogs();
}
private void RemoveServiceEventLogs()
{
foreach (Installer installer in this.Installers)
if (installer is ServiceInstaller)
{
ServiceInstaller serviceInstaller = installer as ServiceInstaller;
if (EventLog.SourceExists(serviceInstaller.ServiceName))
{
eventSources.Add(serviceInstaller.ServiceName, EventLog.LogNameFromSourceName(serviceInstaller.ServiceName, Environment.MachineName));
EventLog.DeleteEventSource(serviceInstaller.ServiceName);
}
}
}
private void serviceProcessInstaller_Committed(object sender, InstallEventArgs e)
{
RemoveServiceEventLogs();
foreach (KeyValuePair<string, string> eventSource in eventSources)
{
if (EventLog.SourceExists(eventSource.Key))
EventLog.DeleteEventSource(eventSource.Key);
EventLog.CreateEventSource(eventSource.Key, eventSource.Value);
}
}
The code could be modified a bit further to only remove the event sources that didn't already exist or create them (though the logname would need to be stored somewhere against the installer) but since my application code actually creates the event sources as it runs then there's no point for me. If there are already events then there should already be an event source. To ensure that they are created, you can just automatically start the service.
I experienced some similar weird behaviour because I tried to register an event source with the same name as the service I was starting.
I notice that you also have the DisplayName set to the same name as your event Source.
On starting the service up, we found that Windows logged a "Service started successfully" entry in the Application log, with source as the DisplayName. This seemed to have the effect of registering Application Name with the application log.
In my event logger class I later tried to register Application Name as the source with a different event log, but when it came to adding new event log entries they always got added to the Application log.
I also got the "The description for Event ID ( 0 ) in Source" message several times.
As a work around I simply registered the message source with a slightly different name to the DisplayName, and it's worked ever since. It would be worth trying this if you haven't already.
The problem comes from installutil which by default registers an event source with your services name in the "Application" EventLog. I'm still looking for a way to stop it doing this crap. It would be really nice if one could influence the behaviour of installutil :(
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.
Adding an empty registry key to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\Application\MY_CUSTOM_SOURCE_NAME_HERE seems to work fine.
An easy way to change the default behavior (that is, that the project installer creates an event log source with the name of your service in the application log) is to easily modify the constructor of the project installer as following:
[RunInstaller( true )]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
public ProjectInstaller()
{
InitializeComponent();
//Skip through all ServiceInstallers.
foreach( ServiceInstaller ThisInstaller in Installers.OfType<ServiceInstaller>() )
{
//Find the first default EventLogInstaller.
EventLogInstaller ThisLogInstaller = ThisInstaller.Installers.OfType<EventLogInstaller>().FirstOrDefault();
if( ThisLogInstaller == null )
continue;
//Modify the used log from "Application" to the same name as the source name. This creates a source in the "Applications and Services log" which separates your service logs from the default application log.
ThisLogInstaller.Log = ThisLogInstaller.Source;
}
}
}

Categories