• Welcome to Overclockers Forums! Join us to reply in threads, receive reduced ads, and to customize your site experience!

Powershell remote event log collection examples

Overclockers is supported by our readers. When you click a link to make a purchase, we may earn a commission. Learn More.

I.M.O.G.

Glorious Leader
Joined
Nov 12, 2002
Location
Rootstown, OH
This first script is an example powershell script that queries the Group Policy event log on remote computers to find trends in machines failing to process user logon policy. Powershell is sweet for certain things like this, where it would be ugly and complex to do in vbscript or other methods. You'd have to run this script under an account with administrative permissions on the machines you want to query.

It does a few noteworthy things:
- skips offline machines
- Filters events to a certain timeframe (past 30 days)
- Uses filterhashtable, which results in less data being transmitted from remote machine rather than sending all log data and filtering it once received
- It collects all group policy 7001 events, then filters those for only messages that contain the word "failed"
- It outputs only the time of the event log, computername, and full event message on a single line to make an easy to read list

It is also noteworthy because it isn't a good powershell script in the truest sense - Most importantly, a good powershell script would be written like a Powershell commandlet, so that it outputs an object that can be handled by other commandlets. Also it would include built in help, a description, and examples if it were a good powershell script in the truest sense - it could be combined and built on top of using other well developed powershell commandlets. This just outputs text, which means the output is for user consumption and can't be elegantly manipulated or fed into other powershell scripts. But like any good script, it does a specific job well.

Code:
#Create a list, one machine per line at C:\targets.txt to collect events from a list of computers
$computers = Get-Content -Path C:\targets.txt

#Uncomment the following line and change the computer name to query just a couple machines
#$computers = "computername1","computername2"

$days = (Get-Date) - (New-TimeSpan -Day 30)

Foreach ($computer in $computers) {
If(Test-Connection -ComputerName $computer -Quiet){
Get-WinEvent -FilterHashtable @{logname='Microsoft-Windows-GroupPolicy/Operational'; id=7001; StartTime=$days} -EA SilentlyContinue -cn $computer | where-object  { $_.Message -like '*failed*' } | select @{label='TimeCreated';expression={$_.TimeCreated.ToString("yyyy-M-d HH:mm:ss")}},MachineName,@{n='Message';e={$_.Message -replace '\s+', " "}}}}

This results in the output that looks like this:
Code:
2016-1-18 09:53:15 computername User logon policy processing failed for domain\user in 1 seconds.   
2016-1-18 09:47:04 computername2 User logon policy processing failed for domain\user2 in 1 seconds.   
2016-1-18 09:45:26 computername3 User logon policy processing failed for domain\user3 in 1 seconds.  
2016-1-18 09:43:28 computername4 User logon policy processing failed for domain\user4 in 1 seconds.   
2016-1-18 09:42:04 computername5 User logon policy processing failed for domain\user5 in 1 seconds.


This example is almost the same, but will create a report of all startup/shutdown times from remote machines for a given period. Event 6005 is when the event log service starts (boot), 6006 is when it stops (shutdown). This will not show 6006 events for loss of power/hard shutdowns via holding the power button, as the event log service isn't able to shutdown when that occurs... So if you see 2 6005 events for a machine without a 6006 inbetween, that indicates the machine experienced a bad power event of some kind.

Code:
#Create a list, one machine per line at C:\targets.txt to collect events from a list of computers
$computers = Get-Content -Path C:\targets.txt

#Uncomment the following line and change the computer name to query just a couple machines
#$computers = "computername1","computername2"

$days = (Get-Date) - (New-TimeSpan -Day 30)

Foreach ($computer in $computers) {
If(Test-Connection -ComputerName $computer){
Get-WinEvent -FilterHashtable @{logname='System'; id=6005,6006; StartTime=$days} -cn $computer | select @{label='TimeCreated';expression={$_.TimeCreated.ToString("yyyy-M-d HH:mm:ss")}},MachineName,@{n='Message';e={$_.Message -replace '\s+', " "}}}}

This results in the output that looks like this:
Code:
2016-1-21 23:01:33 computer1 The Event log service was started.
2016-1-21 14:03:01 computer1 The Event log service was stopped.
2016-1-21 02:10:01 computer1 The Event log service was started.
2016-1-21 02:09:04 computer1 The Event log service was stopped.
2016-1-20 16:08:35 computer1 The Event log service was started.
2016-1-20 16:07:35 computer1 The Event log service was stopped.
2016-1-20 15:58:42 computer1 The Event log service was started.
2016-1-20 14:00:07 computer1 The Event log service was stopped.
2016-1-19 23:54:50 computer1 The Event log service was started.
2016-1-19 23:53:40 computer1 The Event log service was stopped.
2016-1-19 23:01:46 computer1 The Event log service was started.
2016-1-19 14:00:06 computer1 The Event log service was stopped.
2016-1-19 12:38:49 computer1 The Event log service was started.
2016-1-19 12:37:16 computer1 The Event log service was stopped.
2016-1-19 12:33:18 computer1 The Event log service was started.
2016-1-19 08:55:09 computer1 The Event log service was started.
2016-1-18 14:08:06 computer1 The Event log service was stopped.
2016-1-18 08:55:09 computer1 The Event log service was started.
2016-1-17 13:49:27 computer1 The Event log service was stopped.
2016-1-15 23:01:25 computer1 The Event log service was started.
2016-1-14 13:38:29 computer1 The Event log service was stopped.
2016-1-13 23:01:03 computer1 The Event log service was started.
2016-1-21 02:32:38 computer2 The Event log service was started.
2016-1-21 02:30:56 computer2 The Event log service was stopped.
2016-1-19 02:23:05 computer2 The Event log service was started.
2016-1-19 02:22:01 computer2 The Event log service was stopped.
2016-1-15 01:13:38 computer2 The Event log service was started.
2016-1-15 01:12:31 computer2 The Event log service was stopped.

We can tell from these lines above that computer 1 lost power or was hard powered off for some reason on 1/19, because the event log starts twice in a row, without a shutdown event logged inbetween - we may want to follow up with the user to understand if the machine froze, or if they experienced an error leading up to this problem:
Code:
2016-1-19 12:33:18 computer1 The Event log service was started.
2016-1-19 08:55:09 computer1 The Event log service was started.

With these examples, minor changes can be made to these scripts to pull specific event IDs depending on what you are looking to better understand in your Windows environment - a tiny script like this can enable you to get information from the event logs from many machines at once in an easily digestible format, so that you can more quickly and effectively identify trends. It is incredibly useful for both workstations or servers, particularly if you don't have a centralized logging setup.

When researching a tough problem affecting many computers, typically I first manually parse the event log on a specific machine to find relevant events around the time the problem reportedly occurred. Once I find an event that looks interesting related to our problem, I then collect events from a large group of machines to determine how widespread the issue may be and get a trend to start from - if it occurs at certain times, only certain machines, only certain sites or groups. The key is first knowing what you are looking for based on one example machine, then casting a wider net by pulling the logs to better understand what is going wrong in the environment to identify a root cause.

Multithreading these scripts would be incredibly useful, as they take hours to run sequentially against hundreds of machines. But I haven't taken the time to find an implementation I can adapt for that purpose, and for my needs so far letting a report generate over a couple hours has been acceptable though not ideal.