I have a function that archives an event log to a file in a required format.
I'm testing against the windows event logs,Application
,Security
andSystem
. In all tests the code is run with local administrator privileges.
On my development environment the code backs up the each logfile, to what we name an "*.evt" file, succesfully.
On the target reference system theSecurity
andSystem
logs work correctly but processing the Application
log throws a ManagementException
.
An interogation of the exception is included below. My questions are, am I right to assume this is a security privileges issue? What code changes will make this code work for all my desired cases? Failing a definite answer, your thoughts and ideas are appreciated.
ErrorCode: AccessDenied
ErrorInformation: Description: Opened the logfile but failed to back it up, privilige error
Operation: ExecMethod
ParameterInfo: Win32_NTEventlogFile.Name="C:\WINDOWS\system32\config\AppEvent.Evt"
PrivilegesNotHeld:- SeBackupPrivilege
PrivilegesRequired:- SeBackupPrivilege
ProviderName: WinMgmt
StatusCode: 2147749891
using System.Management;
/* ... Omitted for brevity */
public static void WMIBackup(String logName, String targetFile)
{
ManagementScope scope = new ManagementScope("root\\CIMV2");
scope.Options.Impersonation = ImpersonationLevel.Impersonate;
scope.Options.EnablePrivileges = true;
ObjectQuery query = new ObjectQuery(
String.Format("SELECT * FROM Win32_NTEventLog WHERE LogFileName={0}",
logName)
);
using (ManagementObjectSearcher search =
new ManagementObjectSearcher(scope, query))
{
var logs = search.Get();
if (logs.Count != 1)
throw new ArgumentOutOfRangeException("logName not found");
foreach (ManagementObject log in logs)
{
ManagementClass eventLogClass =
new ManagementClass("Win32_NTEventLogFile");
ManangementBaseObject params =
eventLogClass.GetMethodParameters("BackupEventLog");
params["ArchiveFileName"] = targetFile;
log.InvokeMethod(
"BackupEventLog",
params,
new InvokeMethodOptions(
null,
InvokeMethodOptions.InfiniteTimeout)
);
}
}
}
All data is transcribed so apologies for errata.
I've had issues accessing WMI and/or COM interfaces in the past. It would work on one system and fail on another.
I found that the the error did not happen if you retried. I'd suggest that when it fails, you wait for a short period (half a second or so) and retry.
My code has a retry loop around all the COM and WMI calls similar to this sample:
int errorCount = 0;
bool success = false;
while (!success || errorCount < maxRetryCount)
{
try
{
/* Call to WMI interface */
DoSomething();
success = true;
}
catch (Exception ex)
{
if (errorCount < maxRetryCount)
{
logWarning(ex);
}
else
{
logError(ex);
throw; /* pass exception up the stack
or break and handle failure below */
}
}
}
if (!success)
{
/* Handle failure */
}
Never did work out what the underlying issue was, but this works for me.