HowTO: Create an Event Log Source in code, without the Permission errors
在我的程序中需要使用EventLog来写日志,在一般的计算机上可以工作,但是在用户一个受限的计算机上却报错误:“The source was not found,but some or all event logs could not be searched, inaccessible logs:secturity. ”的错误。对此感到很奇怪。在网上搜索找到一篇文章,特转发于此。希望对遇到相同问题的朋友有帮助。
原帖网址: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=439267&SiteID=1
Permissions for the Event log are driven through the registry. Each event log has an entry in the registry under the following key:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog
To allow the ASP.NET account access to create an event source, you need to have read permission on this and all sub keys, and write permission on the event to which you want to create the event source. Part of your error message says " Inaccessible logs: Security.". Note that "Virtual Server" seems to be another common inaccessible log. This means that for the Security log, the ASP.NET account (MachineName\ASPNET) does not have read access to that key.
For reasons that I can't explain, the EventLog.CreateEventSource() method attempts to search Event Sources under all event logs, not just the event log for which you want to create the source. There are two solutions to this. The first, easiest, and most insecure, is just to give read/write access to all event logs for the ASP.NET account. To do this, follow these steps:
The second solution is to bypass the use of the EventLog.CreateEventSource() code, and write your own Event Source addition code, by directly editing adding it to the registry (using code, not regedit!).
Each event source appears as a key below the event log name. So an event source named "MediaManager" under the event log "Hoksoft" would appear as HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\Hoksoft\MediaManager.
An "Event Message File" contains resource strings which format your message content based on parameters. The default .NET message file, EventLogMessages.dll, simply has one parameter "%1", which means that your text is inserted as the message content in its entirity. For further reading on this topic, read http://www.codeproject.com/dotnet/evtvwr.asp. Anyway, to avoid message text similar to the following being displayed...
The description for Event ID ( 0 ) in Source ( MediaManager ) 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:
..., it's necessary to set the EventMessageFile parameter (registry string value) under the subkey for the Event Source. The default location of this file is in the following directory: c:\WINNT\Microsoft.NET\Framework\v2.0.50727\, where v2.0.50727 is the version of the framework you are using (starting with v1.1.x).
The following partial snippet of code should contain enough detail to dynamically create the event log source, without requiring access to other event logs. To use this code snippet, ensure that the following permissions are set:
string eventLogName = "Hoksoft";
string sourceName = "MediaManager";
EventLog hoksoftLog;
hoksoftLog = new EventLog();
hoksoftLog.Log = eventLogName;
// set default event source (to be same as event log name) if not passed in
if((sourceName == null) || (sourceName.Trim().Length == 0))
{
sourceName = eventLogName;
}
hoksoftLog.Source = sourceName;
// Extra Raw event data can be added (later) if needed
byte[] rawEventData = Encoding.ASCII.GetBytes("");
/// Check whether the Event Source exists. It is possible that this may
/// raise a security exception if the current process account doesn't
/// have permissions for all sub-keys under
/// HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog
// Check whether registry key for source exists
string keyName = @"SYSTEM\CurrentControlSet\Services\EventLog\" + eventLogName;
RegistryKey rkEventSource = Registry.LocalMachine.OpenSubKey(keyName + @"\" + sourceName);
// Check whether key exists
if(rkEventSource == null)
{
/// Key does not exist. Create key which represents source
Registry.LocalMachine.CreateSubKey(keyName + @"\" + sourceName);
}
/// Now validate that the .NET Event Message File, EventMessageFile.dll (which correctly
/// formats the content in a Log Message) is set for the event source
object eventMessageFile = rkEventSource.GetValue("EventMessageFile");
/// If the event Source Message File is not set, then set the Event Source message file.
if(eventMessageFile == null)
{
/// Source Event File Doesn't exist - determine .NET framework location,
/// for Event Messages file.
RegistryKey dotNetFrameworkSettings = Registry.LocalMachine.OpenSubKey(
@"SOFTWARE\Microsoft\.NetFramework\");
if(dotNetFrameworkSettings != null)
{
object dotNetInstallRoot = dotNetFrameworkSettings.GetValue(
"InstallRoot",
null,
RegistryValueOptions.None);
if(dotNetInstallRoot != null)
{
string eventMessageFileLocation =
dotNetInstallRoot.ToString() +
"v" +
System.Environment.Version.Major.ToString() + "." +
System.Environment.Version.Minor.ToString() + "." +
System.Environment.Version.Build.ToString() +
@"\EventLogMessages.dll";
/// Validate File exists
if(System.IO.File.Exists(
eventMessageFileLocation))
{
/// The Event Message File exists in the anticipated location on the
/// machine. Set this value for the new Event Source
// Re-open the key as writable
rkEventSource = Registry.LocalMachine.OpenSubKey(
keyName + @"\" + sourceName,
true);
// Set the "EventMessageFile" property
rkEventSource.SetValue(
"EventMessageFile",
eventMessageFileLocation,
RegistryValueKind.String);
}
}
}
dotNetFrameworkSettings.Close();
}
rkEventSource.Close();
/// Log the message
hoksoftLog.WriteEntry(
logMessage,
type,
eventId,
0,
rawEventData);
原帖网址: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=439267&SiteID=1
Permissions for the Event log are driven through the registry. Each event log has an entry in the registry under the following key:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog
To allow the ASP.NET account access to create an event source, you need to have read permission on this and all sub keys, and write permission on the event to which you want to create the event source. Part of your error message says " Inaccessible logs: Security.". Note that "Virtual Server" seems to be another common inaccessible log. This means that for the Security log, the ASP.NET account (MachineName\ASPNET) does not have read access to that key.
For reasons that I can't explain, the EventLog.CreateEventSource() method attempts to search Event Sources under all event logs, not just the event log for which you want to create the source. There are two solutions to this. The first, easiest, and most insecure, is just to give read/write access to all event logs for the ASP.NET account. To do this, follow these steps:
- Start -> Run -> regedit.exe
- Navigate to My Computer > HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog
- Right click this key, select Permissions, and grant the ASPNET account read/write permissions as described above. Note that for the "inaccessible" logs (ie. Security, Virtual Server), you'll also need to grant read access, as permissions have been set to not inherity from the parent key.
- Restart IIS (start -> Run -> iisreset)
- Cause the code line that creates the event source to be executed (EventLog.CreateEventSource())
The second solution is to bypass the use of the EventLog.CreateEventSource() code, and write your own Event Source addition code, by directly editing adding it to the registry (using code, not regedit!).
Each event source appears as a key below the event log name. So an event source named "MediaManager" under the event log "Hoksoft" would appear as HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\Hoksoft\MediaManager.
An "Event Message File" contains resource strings which format your message content based on parameters. The default .NET message file, EventLogMessages.dll, simply has one parameter "%1", which means that your text is inserted as the message content in its entirity. For further reading on this topic, read http://www.codeproject.com/dotnet/evtvwr.asp. Anyway, to avoid message text similar to the following being displayed...
The description for Event ID ( 0 ) in Source ( MediaManager ) 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:
..., it's necessary to set the EventMessageFile parameter (registry string value) under the subkey for the Event Source. The default location of this file is in the following directory: c:\WINNT\Microsoft.NET\Framework\v2.0.50727\, where v2.0.50727 is the version of the framework you are using (starting with v1.1.x).
The following partial snippet of code should contain enough detail to dynamically create the event log source, without requiring access to other event logs. To use this code snippet, ensure that the following permissions are set:
- Read access to ASPNET on the EventLog key: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog
- Read + Write (Full Control OK) on the custom Event Log for your application, eg., for event Log "Hoksoft", on key: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\Hoksoft
- Ensure that the permissions are set to apply to "this key and subkeys".
string eventLogName = "Hoksoft";
string sourceName = "MediaManager";
EventLog hoksoftLog;
hoksoftLog = new EventLog();
hoksoftLog.Log = eventLogName;
// set default event source (to be same as event log name) if not passed in
if((sourceName == null) || (sourceName.Trim().Length == 0))
{
sourceName = eventLogName;
}
hoksoftLog.Source = sourceName;
// Extra Raw event data can be added (later) if needed
byte[] rawEventData = Encoding.ASCII.GetBytes("");
/// Check whether the Event Source exists. It is possible that this may
/// raise a security exception if the current process account doesn't
/// have permissions for all sub-keys under
/// HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog
// Check whether registry key for source exists
string keyName = @"SYSTEM\CurrentControlSet\Services\EventLog\" + eventLogName;
RegistryKey rkEventSource = Registry.LocalMachine.OpenSubKey(keyName + @"\" + sourceName);
// Check whether key exists
if(rkEventSource == null)
{
/// Key does not exist. Create key which represents source
Registry.LocalMachine.CreateSubKey(keyName + @"\" + sourceName);
}
/// Now validate that the .NET Event Message File, EventMessageFile.dll (which correctly
/// formats the content in a Log Message) is set for the event source
object eventMessageFile = rkEventSource.GetValue("EventMessageFile");
/// If the event Source Message File is not set, then set the Event Source message file.
if(eventMessageFile == null)
{
/// Source Event File Doesn't exist - determine .NET framework location,
/// for Event Messages file.
RegistryKey dotNetFrameworkSettings = Registry.LocalMachine.OpenSubKey(
@"SOFTWARE\Microsoft\.NetFramework\");
if(dotNetFrameworkSettings != null)
{
object dotNetInstallRoot = dotNetFrameworkSettings.GetValue(
"InstallRoot",
null,
RegistryValueOptions.None);
if(dotNetInstallRoot != null)
{
string eventMessageFileLocation =
dotNetInstallRoot.ToString() +
"v" +
System.Environment.Version.Major.ToString() + "." +
System.Environment.Version.Minor.ToString() + "." +
System.Environment.Version.Build.ToString() +
@"\EventLogMessages.dll";
/// Validate File exists
if(System.IO.File.Exists(
eventMessageFileLocation))
{
/// The Event Message File exists in the anticipated location on the
/// machine. Set this value for the new Event Source
// Re-open the key as writable
rkEventSource = Registry.LocalMachine.OpenSubKey(
keyName + @"\" + sourceName,
true);
// Set the "EventMessageFile" property
rkEventSource.SetValue(
"EventMessageFile",
eventMessageFileLocation,
RegistryValueKind.String);
}
}
}
dotNetFrameworkSettings.Close();
}
rkEventSource.Close();
/// Log the message
hoksoftLog.WriteEntry(
logMessage,
type,
eventId,
0,
rawEventData);