Search code examples
c#securitywmi

seBackupPrivilige required when backing up Application Event Log with WMI


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,SecurityandSystem. 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 theSecurityandSystemlogs work correctly but processing the Applicationlog 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.


Solution

  • 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.