output type for get-eventlog

by teejay58 at 2013-03-28 12:28:47

I’m trying to write a powershell gui that retrieves event logs from one or several remote machines. Currently I’m having difficulty with the output of get-eventlog. While it works perfectly at the command line, when I run it inside a ps1 file like this:

[code2=powershell]If ($startdate -eq $null) {
write-host "startdate is null"
$startdate = "3/20/2013"
}
write-host "start"
$LogEvents = invoke-command -computername "CompName1" -scriptblock {Get-EventLog -LogName application -entrytype error -after $startdate}
foreach ($event in $LogEvents) {
$event.TimeGenerated
}

write-host "finished"
})[/code2]

I get 5 blank lines on the console. And an error message that indicates $startdate is null or empty.

So the focus of this question is: Why am I getting blank lines in the script and how can I fix that? And why is my $startdate variable empty?
by poshoholic at 2013-03-28 12:41:42
Good questions, I’ll answer them in reverse order.

When you use Invoke-Command to invoke a script block on a remote system, that script block does not automatically inherit variables that you have defined in your local session. You define $startdate locally, not remotely. To fix this you have two possibilities:
1. Use -ArgumentList in your call to Invoke-Command to pass the start date in as an argument, and then internally refer to that argument in the script block you invoke on the remote system. This works for PowerShell 2 and 3.
2. Use the using scope qualifier in your script block to allow you to refer to variables defined locally. This works for PowerShell 3 or later. See Get-Help about_using for examples.

Now the second (first) question: why am I getting blank lines in the script (output) – I presume you mean in the script output here. Consider the difference between these two samples:
Sample 1
$x = Get-Service DoesNotExist -ErrorAction SilentlyContinue
foreach ($item in $x) {
'Hello, we have an item here'
}

Sample 2
$x = @(Get-Service DoesNotExist -ErrorAction SilentlyContinue)
foreach ($item in $x) {
'Hello, we have an item here'
}

If you run these in PowerShell 3, you’ll get the same results every time: no output. In PowerShell 2 however, there was an issue with how foreach treated null. In that version, you would get one line output from PowerShell 2 in the first sample but no lines output in PowerShell 2 in the second sample. I suspect this is why you are seeing blank lines. Wrap your call to Invoke-Command in array enclosures to ensure you always get an array assigned to $LogEvents and the blank line output problem should go away.
by teejay58 at 2013-04-01 17:55:01
Man, this is complicated stuff. Spent another afternoon fooling with scope today. I still don’t understand how it works, but I finally got the startdate to appear inside the scriptblock. Now I’m having problems with the data. It’s giving me object types instead of the value of the objects for $logevent.

$btn_GetEvents.Add_Click({ `

write-host "start"

write-host "before populating logevents"
$script:logevents = invoke-command -computername "CompName1" {
write-host "before get-event"
Get-EventLog -LogName application -entrytype error -after $using:startdate
write-host "after get-event"
write-host "logevents = $script:logevents"
}
write-host "after scriptblock $script:logevents"

$script:LogEvents

foreach ($event in $script:LogEvents) {
$event.TimeGenerated
}

write-host "finished"

})


I included the content of the entire button click function in case it’s relevant. The $startdate variable works now. Thanks for the hint on where to find scope info. I’m still pretty confused about why it works, but at least it does. I suspect that the more I run into scope issues, the more I will start to understand.

However, when I display $script:logevents (either with write-host or just by typing the variable name), my output is all the object type, like this:
System.Diagnostics.EventLogEntry System.Diagnostics.EventLogEntry System.Diagnostics.EventLogEntry

We do have Powershell 3.0 installed. Putting the command into array notation had no effect on the output.

I remain unable to find the correct way to manipulate the $logevents variable so it will produce data. Any help you could provide will certainly be appreciated!
by nohandle at 2013-04-02 02:52:11
Hi, when i run your codes core it works for me:
$script:logevents = invoke-command -computername "localhost" {
#change to newest to make it easier
Get-EventLog -LogName application -entrytype error -Newest 2
}
$script:LogEvents

Index Time EntryType Source InstanceID Message
----- ---- --------- ------ ---------- -------
23427 IV 02 10:35 Error Application Error 1000 Faulting application n...
23266 IV 02 03:32 Error Perflib 3221226495 The description for Ev...


I am also able to get the same input as you by outputing the variable as string both implicitly and explicitly:
Write-Host $script:LogEvents

"$script:LogEvents"
[string]$script:LogEvents

System.Diagnostics.EventLogEntry System.Diagnostics.EventLogEntry
by teejay58 at 2013-04-02 10:56:11
Yes, but did you run it from a script or at the command prompt? I can make it work at the CLI but not from inside a script. That’s what is so difficult about this for me. Also, when I pipe $logevents to get-member at the CLI, the result is different than when I pipe it to get-member inside the script. >.<