Web applications, Windows services, and other applications frequently need to write to an event log on the server. In many cases, it is beneficial to create new event log sources or even new event logs. This allows easier searching for events. Another benefit, in the case of new event logs, this enables custom management of event log size or other maintenance needs. In order to create an event log or source, administrative privileges is required. Consequently, you should never write your application so that it creates an event log or source at run time, because that would require your application to run under administrative privileges. Requiring applications to run as administrator violates a critical rule: Applications should run under an account having least privileges necessary, so that if the service account is compromised, an attacker would not gain administrative privileges over your server.

By having event log sources already created, the application code will write to the event log, assuming the event log source already exists. The developer can choose to write the code in a try / catch block with error handling to alternatively write to a standard event log, text file, database log, etc. according to their design, but that is out of scope for this post. I will focus only on the PowerShell script and execution of it.

This blog posting provides a code example on how to author a PowerShell script that will create event logs and event log sources. If the source already exists, it will give a message indicating such. This script is designed to be executed at time of install of the application, not during run time of the application, thus eliminating the potential security vulnerability of elevation of privileges.

This PowerShell script works without user input, where the application configuration is entered directly into the script as an array of comma delimited pairs of event logs,event log sources. Simply modify the values in the variable $eventSources and run it. In the example given, the $eventSources is configured to create 2 sources on the Application log, then create 2 new event logs with corresponding sources.

Note#1: For the development and test teams, it may be beneficial to use the PowerShell command Remove-eventLog with appropriate parameter -LogName to specify the event log name, or to use the parameter -Source to retain the event log but delete only the event log source. I highly recommend you become familiar with the usage of this command before attempting to delete anything. This functionality is useful for developing and testing purposes of this script, but is not part of the purpose of this blog, so be careful if you use this command for production systems.

Note#2 On some systems, there may be a policy that denies execution of PowerShell scripts. You can override this when calling the PowerShell.exe command by adding -ExecutionPolicy ByPass as a parameter. Policies are there for a reason, but if the script is fully reviewed, tested, and certified, it may be helpful to specify this parameter.

Note#3. Although it is possible to create event logs having greater than 8 characters in the name, if you attempt to create a second event log where the first 8 characters are the same as an existing event log, you will get an error.

# -----------------------------------------------------------------------------
# CreateEventLogSources.ps1
# AUTHOR: Ken O. Bonn
# DATE: 03/29/2014
# PURPOSE: Ensure Event Logs and Sources exist for application "MyApplication" to write events to.
# NOTES: (1)The only customization required is to specify your event log, source pair.
# (2)This can be run from a command prompt as below, assuming policy allows that
# PowerShell.exe -File CreateEventLogSources.ps1
# -----------------------------------------------------------------------------
#
# -----------------------------------------------------------------------------
# CREATE EVENT LOG SOURCES IF THEY DO NOT EXIST.
# -----------------------------------------------------------------------------
#
#eventSources is an array of comma delimited strings containing the Event Log followed by the event source.

$eventSources = @(
"Application,MyApplicationSource1",
"Application,MyApplicationSource2",
"MyAppLg1,MyApplicationSource3",
"MyAppLg1,MyApplicationSource4",
"MyAppLg2,MyApplicationSource5"
)

#Loop through each event log,source pair to create the source on the specified log if it does not exist.

foreach($logSource in $eventSources) {
$log = $logSource.split(",")[0]
$source = $logSource.split(",")[1]
if ([System.Diagnostics.EventLog]::SourceExists($source) -eq $false) {
write-host "Creating event source $source on event log $log"
[System.Diagnostics.EventLog]::CreateEventSource($source, $log)
write-host -foregroundcolor green "Event source $source created"
}
else
{
write-host -foregroundcolor yellow "Warning: Event source $source already exists. Cannot create this source on Event log $log"
}
}