December 15, 2012

.NET: Create EventSource in Windows Event Log (with Admin privileges on Windows7)

Problem
We had one project which logs exception and some system information to Windows Event log. We had to write all logs in appropriate EventSource (created only for our application in Application log). As you may know creating EventSource requires Administrative Privileges on Windows Vista and higher. For deployment we use ClickOnce which does not have such a functionality (i.e. to create event source).

In this article I want to describe solutions that we found, I think maybe most of them (but not all) are obviously for you, but I hope this article will be useful .

Resolving
This is what msdn says about EventSource creation (a full article):
To create an event source in Windows Vista and later or Windows Server 2003, you must have administrative privileges.
The reason for this requirement is that all event logs, including security, must be searched to determine whether the event source is unique. Starting with Windows Vista, users do not have permission to access the security log; therefore, a SecurityException is thrown.
In Windows Vista and later, User Account Control (UAC) determines the privileges of a user. If you are a member of the Built-in Administrators group, you are assigned two run-time access tokens: a standard user access token and an administrator access token. By default, you are in the standard user role. To execute the code that accesses the security log, you must first elevate your privileges from standard user to administrator. You can do this when you start an application by right-clicking the application icon and indicating that you want to run as an administrator.

We don't want to force users to run our application manually by administrator. And we don't want always to run our application with administrative privileges (automatically) to be sure that we can create EventSource whenever we need it.

You may ask: why always to run with admin privileges?
Because it is a standard Windows Vista security mechanism. On application startup Windows will analyze manifest and show 'run as administrator' UAC dialog to a user.
For more information about manifest file, run application with administrator privileges and others - you can read here.

I started to investigate this problem and found few solutions:


Solution 1
Add EventSource directly into registry.
We may create file with next data and run it from our application (with admin privileges):

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\<Your application name>]
"EventMessageFile"=hex(2):43,00,3a,00,5c,00,57,00,69,00,6e,00,64,00,6f,00,77,\
  00,73,00,5c,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,2e,00,\
  4e,00,45,00,54,00,5c,00,46,00,72,00,61,00,6d,00,65,00,77,00,6f,00,72,00,6b,\
  00,5c,00,76,00,34,00,2e,00,30,00,2e,00,33,00,30,00,33,00,31,00,39,00,5c,00,\
  45,00,76,00,65,00,6e,00,74,00,4c,00,6f,00,67,00,4d,00,65,00,73,00,73,00,61,\
  00,67,00,65,00,73,00,2e,00,64,00,6c,00,6c,00,00,00


This script will create a key in the registry with EventMessageFile value for our required EventSource.
EventMessageFile stores the location of the file that contains event identifiers for the events generated by the source program, and a text describing each event (more info).
In this script I used default for value .NET 4.0 application*:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\EventLogMessages.dll
*This value is the same which .NET framework 4.0 will set to created event source after using EventLog.CreateEventSource method.

After running this script user will see a window like that:

As for me this is not a perfect solution, because as you may see this window is not credible and user-friendly. As a user I don't want to click 'Yes' on it and this is a problem.

BTW: You can remove needed EventSource only removing appropriate key from the registry.

Solution 2
Write an own tool which we will run in a separate process with administrative privileges when we need to create Event source.
Example code:

After running this tool with admin privileges user will see this window:

We have here the same problem with not a credible window.
But, you may have your own certificate and sign this 'tool' to avoid this problem but in our situation we don't have it...

Solution 3
Use a standard Windows tool eventcreate.exe
Eventcreate.exe enables an administrator to create a custom event in a specified event log and create event log source if this does not exist. Read more info about this tool here.
We can run next command from our code:
eventcreate  /ID 1 /L Application /T INFORMATION  /SO "EventSourceTest" /D "EventSourceTest source created."
This program is distributed with Windows XP and higher, and signed with Microsoft certificate; so, in such a way a screen with request for administrator privileges looks more pretty.


What we choose
1. In our code we check if needed EventSource is already created.
2. If not then try to create one with current user privileges (not to disturb a user, maybe we already have appropriate permissions).
3. If this operation fails, create EventSource with eventcreate.exe running with administrative privileges.

Complete solution
Instead of a summary I want to show you our completed solution. If you have the same situation, you may use this code and be happy.


4 comments:

Gotta Rock Hard said...

Is it better to use installutil to do the event source creation for the appliation to register itself with the event source being created? I have tried the above and it works fine.

Rostyslav Yaremchuk said...

Installutil.exe will works fine, but this tool may be not installed on user PC.

'This tool is automatically installed with Visual Studio and with the Windows SDK.'
http://msdn.microsoft.com/en-us/library/50614e95.aspx

Anonymous said...

Very good! I have the similar problem and your solution helped me.

Anonymous said...

I've implemented exactly what you have however when I write to the EventSource I created I get a "The description for Event ID 0 from source cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer.

any ideas???