4

The following runs fine on local computer, but when I put -ComputerName "myRemoteName", it hangs and doesn't return anything even after about 5 minutes; but program still seems to be running.

Is it trying to return a large packet of data across the "wire"? In theory, I should have under 10 errors on the remote computer in the last 2 hours.

$getEventLog = Get-EventLog -log application -ComputerName "myRemoteName" -after ((get-date).addMinutes($minutes*-1)) -EntryType Error 
Write-Host Get-Eventlog completed 

# list of events to exclude (based on text found in the message)
$getEventLogFiltered = $getEventLog | Where-Object {$_.Message -notlike 'Monitis*' -and $_.Message -notlike '*MQQueueDepthMonitor.exe*' -and $_.Message -notlike '*The local computer may not have the necessary registry*' }
#to only select certain columns, use Select-Object -Property and list the property/columns                                     
$getEventLogColumns =   $getEventLogFiltered    | Select-Object -Property TimeGenerated,Source,Message,EntryType,MachineName,EventID
$tableFragment = $getEventLogColumns | ConvertTo-Html -fragment
Write-Host "HTML-Table Built"

Code after that builds an email and sends it...

I've seen other posts that suggest switching to Get-WinEvents, but I think that would take me an hour or two to rewrite (due to my lack of experience with Powershell); what I have above is working fine on local computers.

Updates 03/04/2014 13:40 CT: 
   Running with $minutes = 120 ran 14.5 minutes. 
   Running with $minutes = 1   ran 12.5 minutes. 

Conclusion, changing the range of $minutes doesn't really seem to effect the response time; both are slow.

NealWalters
  • 17,197
  • 42
  • 141
  • 251
  • Try something that should run quicker, like `Get-EventLog -logname application -computername myRemoteName -newest 10`. If that comes back quickly it is likely your original command is finding more errors than you think. If not, then likely some configuration issue. IIRC this command uses DCOM for connectivity. – Keith Hill Mar 04 '14 at 15:34
  • I replaced my -after parm with your -newest parm (I put -newest 2) and it came back and sent the email very quickly. There last two errors were around about midnight. This is my Prod system, and I can logon to App Event viewer and verify the number of errors in the application event log. I've been running this script in QA environment for a few months (but no -ComputerName parm). We have older version of Powershell in Prod, so I want to run remotely. Hmmmm... so what now? – NealWalters Mar 04 '14 at 15:40
  • It did eventually come back with the original code, but I was off on other machines not watching it, so no idea how long it took. I'm rerunning now with print of time before & after Get-EventLog. Does the -after filter run on the remote computer? – NealWalters Mar 04 '14 at 17:17
  • So no connectivity/configuration issues are getting in the way. What is your $minutes variable set to? Perhaps you're going back in history further than you think? – Keith Hill Mar 04 '14 at 17:24
  • Try Get-WinEvent and see if runs any faster `Get-WinEvent -cn myRemoteName -FilterHashtable @{LogName='Application'; Level=2; StartTime=(Get-Date).AddMinutes($minutes * -1)}`. – Keith Hill Mar 04 '14 at 17:25
  • @Keith - I just got the official time - 14.5 minutes. I have it set to 120 minutes. I will run again at 1 or 5 minutes and see if it makes any difference. As to Get-WInEvent, see original post - then I have to rewrite the next few lines of codes to use entirely different variables, right? – NealWalters Mar 04 '14 at 17:59
  • First things first. If Get-WinEvent takes the same amount of time then it's a moot point. If it is significantly faster you may be motivated to tweak the rest of the script. – Keith Hill Mar 04 '14 at 19:31
  • Updated original question with run times of $minutes=1 vs $minutes=120 – NealWalters Mar 04 '14 at 19:41
  • I can't seem to get FilterHashTable to work: PS C:\Users\btsadmin> Get-WinEvent -CN "server2" -FilterHashtable @{LogName='Application'} Get-WinEvent : The parameter is incorrect At line:1 char:1 + Get-WinEvent -CN "Dal-biz-app02" -FilterHashtable @{LogName='Application'} + + CategoryInfo : NotSpecified: (:) [Get-WinEvent], EventLogException + FullyQualifiedErrorId : System.Diagnostics.Eventing.Reader.EventLogException,Microsoft.PowerShell.Commands.GetWinEventCommand – NealWalters Mar 05 '14 at 15:04
  • I'm on 3.0 version of PowerShell – NealWalters Mar 05 '14 at 15:14
  • This works on my V3 system. Do you have v3 on both sides? – Keith Hill Mar 06 '14 at 02:30
  • V1 in Prod, V3 in QA. Management afraid to update Prod (until we get new cluster working and deployed, which will be V3 or highter). I was guessing Powershell running remote on QA to PROD would simply use WMI to pull the data back; so it shouldn't matter what version of Powershell is on Prod. – NealWalters Mar 06 '14 at 22:57
  • I can verify that Get-WinEvent works for me going V4 (local) to V2 (remote). – Keith Hill Mar 06 '14 at 23:15
  • Keith - thanks for testing; this is why I must admit I like C# a language I know over Powershell. I have no idea what the "parameter is incorrect" and "CategoryInfo : NotSpecified" error reported above means. I did of course google it. And still not sure why Get-EventLog is slow. I'm doing this in my spare time, not a real project. Powershell seemed good for building a quick email, and worked fine on my QA environment. – NealWalters Mar 07 '14 at 14:59
  • Looks like a bug in PowerShell http://connect.microsoft.com/PowerShell/feedback/details/689962/powershell-filterhashtable-on-windows-server-2008-rtm – Keith Hill Mar 07 '14 at 16:54

2 Answers2

3

After parameter is not very well designed, it prints all records it suppose to, but when it reaches set date it stills scans till the end of even log file despite the fact, that there is nothing to print (at least it looks so). I've used Where-object filter and .CompareTo() method to prints logs which are after set date (in my case a day before current date).

#Sets yesterday date (script will get all records after that date)

$YDate = (Get-Date).AddDays(-1)

#Gets all event logs from Security log where event id represents successful logon and records where generated after prepared date (current date - 24 hours)

$YestardayLogons = Get-EventLog -ComputerName $ServerName -LogName Security | 
    WHERE { ($_.EventId -eq '528') -and ($_.TimeGenerated.CompareTo($YDate) -eq '1') }
Matt
  • 45,022
  • 8
  • 78
  • 119
Wojciech
  • 76
  • 3
  • Thanks, sounds reasonable. I cannot validate because I'm at a different client now. – NealWalters Mar 31 '15 at 13:07
  • If I understand it correctly then the WHERE command is piped to the Get-EventLog command. This means, the WHERE command will work on the results from the Get-EventLog command. That again means that the Get-EventLog command will still scan all events, so there will be no improvement to the performance compared to the -After command. – AndyZ Feb 28 '17 at 11:58
2

It seems that I was wrong, even with Where-Object filter it still scans like in case of -after parametr (I was just testing on different, freshly build machine and this is why it finished so quickly).

Additional research showed however that break function could be useful, so what I did was:

Get-EventLog -ComputerName $ServerName -LogName Security | WHERE { ($_.EventID -eq '528')} | ForEach-Object {
  $_
  if ($_.TimeGenerated.CompareTo($YDate) -lt 1) { Break}
}

It prints all event logs and when it hits event log older than (in my case 24 hours) break kicks in and stops get-eventlog cmdlet.
It is not the most pretty solution but it seems to be working fine so far.

Matt
  • 45,022
  • 8
  • 78
  • 119
Wojciech
  • 76
  • 3
  • Marking as answer, even though I have not tested. – NealWalters Apr 01 '15 at 15:27
  • 1
    Just one more comment to that - as much as **break** works fine in case of single servers, when I was using this in a loop to scan multiple servers break was not only terminating cmdlet but whole script. To avoid that I used **try{} catch{}** and inside of my **if** instruction instead of **break** I forced error by **[int]$Error = "Error"** assignment. This cause cmdlet termination due to **try{} catch{}** mechanizm. Other option maybe more pretty is using **Trow** instruction (also combained with **try{}catch{}** mechanism). – Wojciech Apr 03 '15 at 11:12