Question: Is it possible to export an event log in a process not "run as administrator"?
I'm following the example code at https://msdn.microsoft.com/en-us/library/bb671203(v=vs.90).aspx
using (var els = new EventLogSession())
{
els.ExportLogAndMessages("Security", PathType.LogName, "*", @"c:\temp\security.evtx");
}
This code runs successfully when I run the process using "run as administrator", but fails when not "run as administrator with the exception
System.UnauthorizedAccessException:
"Attempted to perform an unauthorized operation."
Using similar code to access my application's event log
using (var els = new EventLogSession())
{
els.ExportLogAndMessages("MyAppLog", PathType.LogName, "*", @"c:\temp\myapplog.evtx");
}
I get similar results except the exception is different:
System.Diagnostics.Eventing.Reader.EventLogException: "The directory name is invalid"
Am I doing something wrong, or is there a different approach that will allow me to get an event log exported to an .evtx file without requiring admin privileges?
Notes:
- Under the hood, I believe this is calling (and failing) in the native method
EvtArchiveExportedLog
.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa385232(v=vs.85).aspx
- As such the following seems related: EvtArchiveExportedLog fails with ERROR_DIRECTORY , but I don't understand what I would need to do in order to make my situation work correctly.
Question: Is it possible to export an event log in a process not "run as administrator"?
Yes you can but only if you have the rights to access the event log you want to export.
However, your question seems to be more something like
Why can't I export my application's event log using EventLogSession
? An EventLogException
is thrown with the message "The directory name is invalid".
Looking into the source code for EventLogSession
you can see that the call to ExportLogAndMessages
will call the native function EvtExportLog
. If this function fails the error code is retrieved by calling GetLastError
. This native Windows error code is then mapped to one of several exceptions.
The exception that you experience is thrown if any of the following errors happen:
- ERROR_FILE_NOT_FOUND (2): The system cannot find the file specified.
- ERROR_PATH_NOT_FOUND (3): The system cannot find the path specified.
- ERROR_EVT_CHANNEL_NOT_FOUND (15007): The specified channel could not be found. Check channel configuration.
- ERROR_EVT_MESSAGE_NOT_FOUND (15027): The message resource is present but the message is not found in the string/message table.
- ERROR_EVT_MESSAGE_ID_NOT_FOUND (15028): The message id for the desired message could not be found.
- ERROR_EVT_PUBLISHER_METADATA_NOT_FOUND (15002): The publisher metadata cannot be found in the resource.
If you specify a wrong event log name then ERROR_EVT_CHANNEL_NOT_FOUND is the error you encounter. My guess is that this is your problem.
However, you can call EvtExportLog
yourself and inspect the native error code to better understand why the call fails:
[DllImport("kernel32.dll")]
static extern uint GetLastError();
[DllImport("wevtapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EvtExportLog(IntPtr session, string channelPath, string query, string targetFilePath, int flags);
var success = EvtExportLog(IntPtr.Zero, "MyAppLog", "*", @"c:\temp\myapplog.evtx", 1);
if (!success)
{
var error = GetLastError();
Console.WriteLine(error);
}
The native error code should give you a clear indication of what the underlying problem is.
Using the approach shown on pinvoke.net works without admin privileges for my custom application log (i.e. MyAppLog
in the example above). This does not work for Security
log example shown above (but I believe that is intended):
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern IntPtr OpenEventLog(string UNCServerName, string sourceName);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool BackupEventLog(IntPtr hEventLog, string backupFile);
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool CloseEventLog(IntPtr hEventLog);
void SaveLog(string eventLogName, string destinationDirectory)
{
string exportedEventLogFileName = Path.Combine(destinationDirectory, eventLogName + ".evtx");
IntPtr logHandle = OpenEventLog(Environment.MachineName, eventLogName);
if (IntPtr.Zero != logHandle)
{
bool retValue = BackupEventLog(logHandle, exportedEventLogFileName);
//If false, notify.
CloseEventLog(logHandle);
}
}