Last time we looked at using PowerShell to query the state of classic Event Log entries, as well as set some limits. If you missed that article, please take a moment to get caught up. Today I want to demonstrate some techniques for backing up the event logs. I’ll cover clearing the Event Log in a future article.
Avatar

Backup an Event Log

If you look through the Event Log related cmdlets, you’ll notice there is no cmdlet for backing up an Event Log. This is unfortunate, but not insurmountable. You simply have to take matters into your own hands. I’ll walk you through the process. Once you understand how it works, you could create your own PowerShell script or function.

I’ll first test everything locally. To back up the Event Log file, we’ll need to use WMI so I’ll first get a log.

PS C:\> $log = get-wmiobject win32_nteventlogfile -filter "logfilename = 'Windows PowerShell'"

The logfile object has a method called BackupEventlog which takes a filename as a parameter.

PS C:\> $log.BackupEventlog

OverloadDefinitions
-------------------
System.Management.ManagementBaseObject BackupEventlog(System.String ArchiveFileName)

The file you specify for the archive backup is relative to the local computer. This will be significant when we get to backing up logs on remote computers. For now, I can backup the file to a local path.

PS C:\> $log.BackupEventlog("c:\work\powershell.evtx")

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     :
__DYNASTY        : __PARAMETERS
__RELPATH        :
__PROPERTY_COUNT : 1
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ReturnValue      : 0
PSComputerName   :

A return value of 0 indicates success. I could also backup to a UNC.

PS C:\> $log.BackupEventlog("\\chi-fp01\it\$env:computername-powershell.evtx")

One drawback to this technique is that there is no way to test the command. There is no –WhatIf. But we can get that by using Invoke-WMIMethod.

PS C:\> $file = "{0}_{1}_{2}.evtx" -f (get-date -f "yyyyMMdd"),$env:computername,$log.FileName.Replace(" ","")
PS C:\> $backup = join-path "\\chi-fp01\it" $file
PS C:\> $log | Invoke-WmiMethod -Name BackupEventlog -ArgumentList $backup -whatif

If I’m satisfied I can do it for real. You can see the result below:

EventLog - Backup

Event Log - Backup

I created a backup file name that used the current date, computer name and log file name with the spaces removed.

If a file with the same name already exists you will get a ReturnValue of 80. That’s why I always try to devise a unique name.

Remote backups

Now let’s scale out and try this remotely with the following code:

$log = get-wmiobject win32_nteventlogfile -filter "logfilename = 'Windows PowerShell'" -ComputerName CHI-FP02
$file = "{0}_{1}_{2}.evtx" -f (get-date -f "yyyyMMdd"),$log.PSComputerName,$log.FileName.Replace(" ","")
$backup = join-path "\\chi-fp01\it" $file
$log | Invoke-WmiMethod -Name BackupEventlog -ArgumentList $backup

Unfortunately, when I try to run this, I’ll get AccessDenied. That’s because I can’t make a second hop. If I change the backup file to a local folder, it will work as expected. I could mess around with CredSSP. But Instead I’ll use PowerShell remoting and add a step to authenticate to the second hop.

$cred = Get-Credential globomantics\administrator

invoke-command -ScriptBlock {
  $log = get-wmiobject win32_nteventlogfile -filter "logfilename = 'Windows PowerShell'" -EnableAllPrivileges
  $file = "{0}_{1}_{2}.evtx" -f (get-date -f "yyyyMMdd"),$log.CSName,$log.FileName.Replace(" ","")
  #map a PSDrive with credentials
  New-PSDrive -name B -PSProvider Filesystem -Root \\chi-fp01\it -Credential $using:cred | Out-Null
  dir B:\*.evtx | write-host -ForegroundColor yellow
  #backup path must be something Windows can see like a UNC
  $backup = join-path (get-psdrive B).root $file
  write-host "Backing up to $backup" -ForegroundColor cyan
  $r = $log | Invoke-WmiMethod -Name BackupEventlog -ArgumentList $backup
  if ($r.returnValue -eq 0) {
    Get-Item $backup
  }
  else {
   Throw "Backup failed with returnvalue $($r.returnvalue)"
  }

 } -ComputerName chi-fp02

The code I’m using is for PowerShell 3.0 so that I can take advantage of the Using: prefix. Otherwise I’d have to construct the script block to take parameters and pass values. Everything in the script block runs on the remote computer, in this case CHI-FP02. On the remote computer I create a temporary PSDrive to the shared folder, using the credential to authenticate. The use of a credential to map a PSDrive is new to PowerShell 3.0 so if you were to try this against a PowerShell 2.0 system, it will fail. It doesn’t matter what name I use for the PSDrive, but the actual backup path must be something Windows can see which is why I get the PSDrive’s Root property. I’ve also tossed in a little error handling. My result can be seen below:

EventLog - Remote backup

Event Log - Remote backup

Here’s a more complete script that backs up the Application Event Log from a number of computers that are all running PowerShell 3.0.

#requires -version 3.0

#remote computers must be running PowerShell 3.0

$computers = "chi-dc01","chi-fp01","chi-dc04","chi-fp02"
$cred = Get-Credential globomantics\administrator
$eventlog = "Application"

invoke-command -ScriptBlock {
  $log = get-wmiobject win32_nteventlogfile -filter "logfilename = '$using:eventlog'"
  $file = "{0}_{1}_{2}.evtx" -f (get-date -f "yyyyMMdd"),$log.CSName,$log.FileName.Replace(" ","")

  #map a PSDrive with credentials
  New-PSDrive -name B -PSProvider Filesystem -Root \\chi-fp01\it -Credential $using:cred | Out-Null

  #backup path must be something Windows can see like a UNC
  $backup = join-path (get-psdrive B).root $file
  write-host "Backing up to $backup" -ForegroundColor cyan
  $r = $log | Invoke-WmiMethod -Name BackupEventlog -ArgumentList $backup
  if ($r.returnValue -eq 0) {
    Get-Item $backup
  }
  else {
   Throw "Backup failed with returnvalue $($r.returnvalue)"
  }

 } -ComputerName $computers

And here’s the result:

EventLog - Remote backup 2

Event Log - Remote backup

 This runs pretty quickly because the backup process occurs simultaneously on each remote system.

Summary

If you don’t want to mess with credentials and remote paths, you can always create the backup locally on the remote computer and have a separate process if you need to move the files to a central location. The techniques I showed above require PowerShell 3.0 and if you have that, there are some perhaps better ways to accomplish Event Log backups. We’ll look at those next time.

Articles in seriesEvent Log and PowerShell
2 Comments
  1. Avatar
    Pawan Kumar 6 years ago

    Thanks,

    How can i get last 24 hour Eventlog of Application or System Event. Could you please tell me ?

  2. Avatar

    $Log.BackupEventlog can’t find Microsoft-Windows-CAPI2/Operational, even though $logName = ‘Microsoft-Windows-CAPI2/Operational’

    $log = New-Object System.Diagnostics.Eventing.Reader.EventLogConfiguration $logName
    has no problem.

Leave a reply

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account