Get-WinEvent in a remote session gives an error

I’m playing with the cmdlet Get-WinEvent I see something happening that I don’t understand.

This is what I’m doing.

For example, the following two commands give me back a result.

$FilterHashTable = @{logname='System','Application'; StartTime=(Get-Date).Date.AddDays(-1); Level=2,3};
Get-WinEvent -FilterHashtable $FilterHashTable -ComputerName localhost | Select-Object TimeCreated, LevelDisplayName, Message, logname;

So that showes me that it is allowed to work with more than one logname and with more than one loglevel.

When I examine $FilterHashTable, I see that it’s typename is System.Collections.Hashtable. With for example $FilterHashTable.logname[0] being ‘System’ and $FilterHashTable.logname[1] being ‘Application’. That looks ok to me.

When I do the following, I get the error message: "There is not an event log on the localhost computer that matches “System Application”.

$FilterHashTable = @{logname='System','Application'; StartTime=(Get-Date).Date.AddDays(-1); Level=2,3};
Invoke-Command -ScriptBlock {param ($FilterHashTable) Get-WinEvent -FilterHashtable $FilterHashTable} -ArgumentList $FilterHashTable -ComputerName localhost

As a final test I do this, only 1 logname and only 1 loglevel.

$FilterHashTable = @{logname='System'; StartTime=(Get-Date).Date.AddDays(-1); Level=2};
Invoke-Command -ScriptBlock {param ($FilterHashTable) Get-WinEvent -FilterHashtable $FilterHashTable} -ArgumentList $FilterHashTable -ComputerName localhost

And this one works, just like the first one.

Does anyone know why the second construct won’t work? Am I doing something wrong in the second construct? Or is it just impossible to do this in one command?

My aim is to run this to get today’s or yesterday’s errors and warnings from multiple servers, preferably presenting the message, logname and computername in one flow of objects. And the second construct looks good, so I’m curious whether there is a way to get it to work.

By the way, I’ve tried this with Powershell v4 against Windows 2012R2 and against Windows 8.1, but also with Powershell v3 against Windows 7 and Windows 2008R2. Both gave the same error on the second construct.

The reason of this behavior is how PowerShell objects are sent to remote sessions, see the following link:

A way around this might be to build the hashtable in the remote session, instead of providing it as a parameter

Invoke-Command -ScriptBlock {

$FilterHashTable = @{logname='System','Application'; StartTime=(Get-Date).AddDays(-1); Level=2,3}
Get-WinEvent -FilterHashtable $FilterHashTable 

} -ComputerName localhost

Thanks, your comment is most helpful. Sounds logical, not only that what is coming back from the remote computer is deserialized, but also that what is sent to the remote computer.

My next experiment was this.

$DaysBackInTime = 2;
$strCmd = @"
            $FilterHashTable = @{logname='System','Application'; StartTime=(Get-Date).Date.AddDays(-$DaysBackInTime); Level=2,3};
            Get-WinEvent -FilterHashtable $FilterHashTable;
$cmd = [Scriptblock]::Create($strCmd);

Invoke-Command -ScriptBlock $cmd -ComputerName localhost, dc | Select-Object PSComputerName, TimeCreated, LevelDisplayName, logname, Message | Sort-Object TimeCreated;

Beware, in the above code block I had to remove the backtick before $FilterHashTable. So, $FilterHashTable should be read as `$FilterHashTable.

And it works. Now I can do variable substitution, I can ask multiple computers in one command and I get back objects in the pipeline. Now I think that I have a way to discover potential coherency in issues on multiple servers. For example, an issue on server A, responsible for part x of the application, causes an issue on server B, responsible for part y of the application. I don’t know if these issues exist on the servers I’m responsible for, but now I have a way to find out.