More Fast & Furious: Remote Event Logs

The other day, I demonstrated a fast &furious way to check eventlogs on the local computer. Unfortunately the Get-Eventlog cmdlet doesn’t have a remote computer option. To get event logs from remote computers, you need to use Get-WMIObject. Unfortunately,this requires a bit more work.

Here’s the code you would need to run:

$computer=”MyServer”
foreach ($log in (Get-WmiObject win32_nteventlogfile -computer $computer | Select-Object logfilename)) {
Write-Host -fore Green -back Black $log.logfilename ;
$query=”Select Eventcode,Eventtype,Logfile,Message,TimeGenerated from win32_NTLogEvent where logfile=’”+$log.logfilename+”’”;
Get-WmiObject -query $query -computer $computer | Select-Object EventCode,EventType,LogFile,Message,TimeGenerated -first 10 | More
}

Hardly a friendly one-liner. Parsing out the eventlog file names is a little more cumbersome:

Get-WmiObject win32_nteventlogfile -computer $computer | Select-Object logfilename

But once I have them, I can build a query:

$query=”Select Eventcode,Eventtype,Logfile,Message,TimeGenerated from win32_NTLogEvent where logfile=’”+$log.logfilename+”’”;
And then run Get-WMIObject, again selecting just the information I want and piping it to More:

Get-WmiObject -query $query -computer $computer | Select-Object EventCode,EventType,LogFile,Message,TimeGenerated -first 10 | More

I tried using the query directly, but the -query parameter didn’t like $log.logfilename. Since having a separate query worked, I moved on.

If you run this, it will look fine at first glance. But then you’ll realize you didn’ t see anything from Security eventlog. To access the Security Eventlog, you need to specify the Security Privilege. Unfortunately, the Get-WMIObject cmdlet has no such provision. The way around this is to use a WMISearcher object and enable privileges. You’ll also need to specify the remote computer in the scope.path:

$searcher=new-object WMISearcher

$searcher.Scope.Options.EnablePrivileges=1

$searcher.scope.path=\$computer\root\cimv2

Here’s what the modified code would look like:

$computer=”dc01”
$searcher=new-object WMISearcher
$searcher.Scope.Options.EnablePrivileges=1
$searcher.scope.path=”\$computer\root\cimv2”
foreach ($log in (Get-WmiObject win32_nteventlogfile -computer $computer | Select-Object logfilename)) {
Write-Host -fore Green -back Black $log.logfilename ;
$query=”Select Eventcode,Eventtype,Logfile,Message,TimeGenerated from win32_NTLogEvent where logfile=’”+$log.logfilename+”’”
$searcher.query=$query
$searcher.get() | Select-Object EventCode,EventType,LogFile,Message,TimeGenerated -first 5 | More
}

This should work, assuming you are running this with domain admin credentials. If you need to specify alternate credentials, then you not only have to pass them to the Get-WMIObject, but you also need to define them for the searcher object. But here’s the problem: the Get-WMIObject wants a secure string password, but the searcher object can only take plain text. I tried passing the results of ConvertFrom-SecureString as the searcher password, but no-go.

Eventually this is what I came up with:

$computer=”dc01”
$username=”mydomain\administrator”
#password has to be entered as clear text
$pw=Read-Host “Enter the password you’ll need”
#but credential requires secure string
$securepw=ConvertTo-SecureString $pw -AsPlainText -Force
$cred=new-object -typename System.Management.Automation.PSCredential -argumentlist $username,$securepw
$searcher=new-object WMISearcher
$searcher.Scope.Options.EnablePrivileges=1
$searcher.scope.path=”\$computer\root\cimv2”
$searcher.scope.options.username=$cred.Username
$searcher.scope.options.password=$pw

foreach ($log in (Get-WmiObject win32_nteventlogfile -computer $computer -credential $cred| Select-Object logfilename)) {
Write-Host -fore Green -back Black $log.logfilename ;
$query=”Select Eventcode,Eventtype,Logfile,Message,TimeGenerated from win32_NTLogEvent where logfile=’”+$log.logfilename+”’”
$searcher.query=$query
$searcher.get() | Select-Object EventCode,EventType,LogFile,Message,TimeGenerated -first 5 | More
}

As you can see, hardly a fast & furious solution and far from elegant.  The password you enter will be displayed as plain text. But this gets the job done. Although, if your logs are too big you might get a quota violation.  I’ll have to deal with that later.

This task would be a whole lot easier if Get-Eventlog could query remote computers, or Get-WMIObject could set privileges. Actually, it would be great if both cmdlets could be enhanced to povide these features.