Scripting with Windows PowerShell Part 3
Working with Windows Management Instrumentation (WMI) information to retrieve essential information
Part 3 of a 5 part series.
Event logs
These commands will work on the local machine or a machine across the network. Most of the EventLog commands accept Computer name as an option, but do not accept any credentials. So connections made to a another machine must be able to impersonate you. If the security hasn’t been set up that way then you must use a different method such as the PowerShell Remoting commands (Invoke-Command), WMI (with Get-WmiObject) or Enter-PSSession.
Get-EventLog -ListLists all the classic event logs. Classic seems to refer to the log names that were around years ago in NT3/NT4 days, but this list contains classic and new logs. So Ed Wilson, we’re just refer to this list of logs as a list of logs - ya’know to avoid any confusion!
Max(K) Retain OverflowAction Entries Log ------ ------ -------------- ------- --- 512 7 OverwriteOlder 724 ACEEventLog 20,480 0 OverwriteAsNeeded 4,146 Application 20,480 0 OverwriteAsNeeded 0 HardwareEvents 512 7 OverwriteOlder 0 Internet Explorer 20,480 0 OverwriteAsNeeded 0 Key Management Service 8,192 0 OverwriteAsNeeded 0 Media Center 128 0 OverwriteAsNeeded 11 OAlerts 20,480 0 OverwriteAsNeeded 4,621 Security 20,480 0 OverwriteAsNeeded 7,618 System 15,360 0 OverwriteAsNeeded 231 Windows PowerShell ...The “Windows PowerShell” (above) log is pretty useless and will probably just have a load of messages saying “powershell started". We can read a log by using its log name on the command line:
Get-EventLog -LogName application -Newest 5
Index Time EntryType Source InstanceID Message ----- ---- --------- ------ ---------- ------- 4146 Jun 03 16:23 Information Office Software P... 1073742827 The Software Protection service has completed 4145 Jun 03 12:06 Information McLogEvent 1073746824 McShield service started.... 4144 Jun 03 11:05 Information Windows Error Rep... 1001 Fault bucket , type 0... 4143 Jun 03 11:05 Information McLogEvent 1073742081 The scan of D:\DOWNLO~1\ECLIPS~2.ZIP has taken 4142 Jun 03 11:05 Information McLogEvent 1073742081 The scan of D:\DOWNLO~1\ECLIPS~1.ZIP has takenEach one of the entries has 6 columns, but as we know from previous lessons these 6 columns are just a cut down version of what is available. To see more we’ll use the Format-List to show them all:
Get-EventLog -LogName application -Newest 1 | Format-List *
EventID : 1003 MachineName : cuckmere.example.com Data : {} Index : 4146 Category : (0) CategoryNumber : 0 EntryType : Information Message : The Software Protection service has completed licensing status check. Application Id=59a52881-a989-479d-af46-f275c6370663 InstanceId : 1073742827 TimeGenerated : 03/06/2011 16:23:19 TimeWritten : 03/06/2011 16:23:19 UserName : Site : Container :It might be nice to see on what other occasions The Software Protection service ran.
Get-EventLog -LogName application | Where { $_.message -match ‘protection’ }The -match takes a regular expressions so in our case it is looking for the word “protection” anywhere on the line. The results come back and you may have to take advantage of the control+c keyboard sequence to stop the current command.
Index Time EntryType Source InstanceID Message ----- ---- --------- ------ ---------- ------- 4146 Jun 03 16:23 Information Office Software P... 1073742827 The Software Protection service has comple 4116 May 31 14:28 Information Office Software P... 1073742827 The Software Protection service has comple 4115 May 31 14:28 0 Office Software P... 1073742726 The Software Protection service has starte 4114 May 31 14:28 Information Office Software P... 1073742890 Initialization status for service objects. 4113 May 31 14:28 Information Office Software P... 1073742724 The Software Protection service is startin ...Ed tried to make excuses for the slowness of his results being displayed. “But that’s cool because we’re filtering out through a whole lot of entries, then doing a match of the message, and it’s like having to read all the messages and look for that sequence of characters.” - Really? I mean you would expect a little delay between the results being displayed, but not that much. It looks to me like he hadn’t installed the graphics card on his PC properly and the scroll rate had dropped through the floor - that old chestnut ;) Anyway I tried it and it was fine. With event logs we can filter on InstanceID by adding the -InstanceId switch.
Get-EventLog -LogName application -InstanceId 1073742827While the results are equivalent to a statement containing a Where-Object cmdlet, it is much quicker because the instance filtering is done inside the Get-EventLog cmdlet i.e. the non-matching InstanceId records never have to travel down the pipe. Wow, that’s another 5 minutes I’ll never get back.
Get-EventLog -LogName application |where {$_.InstanceId -eq 1073742827}Let’s say we want to filter on Source. We can’t see all of the Source name so we can expand that column using the Select-Object cmdlet (Select is an alias for Select-Object):
Get-EventLog -LogName application -InstanceId 1073742827 -Newest 5 | select source
Source ------ Software Protection Platform Service Windows Search Service Office Software Protection Platform Service Office Software Protection Platform Service Software Protection Platform ServiceAll values of the source column have been fully expanded. For the purpose of expanding column names we could have just used one of the format cmdlets (Format-Table / Format-List). Select-Object is supposed to manipulate lists of objects such as finding unique entries or returning a sub-list. So to finish the previous example, we can specify the full source name or we can use a wild card:
Get-EventLog -LogName application -Source “Software Protection Platform Service” Get-EventLog -LogName application -Source “Software Protec*”In the past Ed’s “always hated typing dates, erm… simply for the fact, y’know, you never really know exactly how these things are going to be interpreted, and all of that", but not with PowerShell because there are filter switches of -Before and -After. Perhaps he should revisit the other search applications and read the instructions! The -Before and -After switches expect dates so the format is pretty flexible and is based on your locale or as they call it Culture. To find out which Culture you are in, issue the command:
Get-Culture
LCID Name DisplayName ---- ---- ----------- 2057 en-GB English (United Kingdom)Getting back to our date filtering example. An interesting shortcut is that -A is short for -After, -B is short for -Before and as it turns out you can shorten a switch to it’s minimum unique name. For example on Get-EventLog the shortest switch for -LogName is -LogN because if you tried -Log it would interfere with -Log which has a different function.
Get-EventLog -LogName application -After 01-06-2011 -Before 02-06-2011 Get-EventLog -LogName application -A “1 June 11″ -B “2 Jun 2011″ Get-EventLog -LogName application -Aft “1 - 06 - 11″ -Bef “2 / 6 / 2011″Event Trace Logs (ETL) Event Trace Logs (ETL) is EventLog version 2. There are a different set of cmdlet tools to hope with the new format of the logs and the additional data held in those logs. The new version is backward compatible with the old classic style of logging, so you could avoid using Get-EventLog in favour of Get-WinEvent. ETL was introduced in Vista and is available in operating systems after that. Load the Event Viewer using Start -> Control Panel -> Administration -> Windows Event Viewer. Under Windows Logs there are the classic logs, under that is the Application and Service Logs are more of the logs that are available with the Get-EventLog cmdlet, but are some how not classic. We are going to be looking at the Trace and Debug logs. The first got-cha is that these logs don’t show up by default, you have to explicitly switch them on. From the Event Viewer panel highlight Application and Service Logs and file menu make sure that View -> Show Analytic and Debug Logs is checked. Application and Service looks like a place to contain logs from other companies. These new logs (or style of logs) split the data into different categories like Operation, Verbose, Analytic, etc. Operational logs seem to be switched on by default where as Trace, Diagnostic and others seem to be switched off by default. As you can see there are literally hundreds of log files available, so you can find information on almost any kind of issue that the system might be going through. We are going to be looking at WMI activity so scroll down to WMI-Activity. When we click on the log icon (in the panel view) we get a list of the current log entries. Trace logs are switched off so we must enable it explicitly. Right-click on the log icon and select Enable Log. There is a scary warning about losing log entries when this is enabled so in Ed’s words: “it’s gonna whine, and I say yeh, yeh, yeh, so this is cool". When the scary message says “lose events” I think it means lose them from the view as opposed to them disappearing down a black hole. It would have been another: “Thanks Bill” for creating a logging system that is either disabled or almost-enabled! So let’s now list those logs via PowerShell. The first thing to deal with is the got-cha I mentioned above. Just like the trace and diagnostic logs needed explicitly enabling in the Event Viewer; they need explicitly switching on in the PowerShell too. This is achieved with the -Force switch. The -Force switch works in combination with the -LogName switch. If you specify the -LogName name (in full) then Get-WinEvent will allow you access to that one log. If you use a wildcard in the -LogName only the Operational level log files will be used in the search space to find a match. If you use a wildcard in the -LogName and -Force then the log files, including all the Trace and Diagnostic logs, will be used in the search. The following 3 examples will help show the effects of this. Some of the entries may be blank because you don’t have the right privileges to see them. I have expanded the -LogName so that you can see the difference but when you do it they may be truncated, so don’t forget you can use Select-Object to only display the columns you want.
Get-WinEvent -ListLog “*CodeIntegrity*”
LogName MaximumSizeInBytes RecordCount LogMode ------- ------------------ ----------- ------- Microsoft-Windows-CodeIntegrity/Operational 1052672 4 Circular
Get-WinEvent -ListLog “*CodeIntegrity*” -Force
LogName MaximumSizeInBytes RecordCount LogMode ------- ------------------ ----------- ------- Microsoft-Windows-CodeIntegrity/Operational 1052672 4 Circular Microsoft-Windows-CodeIntegrity/Verbose 1052672 Retain
Get-WinEvent -ListLog “Microsoft-Windows-CodeIntegrity/Verbose”
LogName RecordCount ------- ----------- Microsoft-Windows-CodeIntegrity/Verbose 1052672A bit of advice from Ed:
- “‘Use the Force Luke’, even if you’re name isn’t Luke you can still use the Force”
- “You’ll need to use the Force parameter only often enough, that when you do need to use it, you’ll probably forget about it, well at least that’s my behaviour anyway.”
- “You’ll have to actively train yourself to try and add this Force parameter, now if this is something you really don’t like, then you can actually write a function that wraps this cmdlet and automatically adds the Force to it, so that you don’t have to add it.”
Get-WmiObject -Class win32_bios gwmi -Class win32_bios gwmi win32_biosTo give yourself something to look at in the PowerShell ISE enter the following command in to the top script panel and run it:
Get-WinEvent -LogName Microsoft-Windows-WMI-Activity/Trace -Oldest | where { $_.message -match ‘Class’ } | select message -ExpandProperty messageDon’t worry if the PowerShell ISE introduction didn’t make any sense, because it didn’t to me either! PowerShell ISE is better then the blue command box because it is more colourful and it allows you to save the command text separately. Other than that, PowerShell ISE is a pretty poor attempt at a integrated development environment. Ed Wilson is the Microsoft man for PowerShell and runs the HeyScriptingGuy blog site on Technet. He has a page devoted to logs and monitoring: http://blogs.technet.com/b/heyscriptingguy/archive/tags/event+logs/windows+powershell/logs+and+monitoring/ You can save an event log then you can use Get-WinEvent to parse that saved log. You can store all your event logs in a single location, use Get-ChildItem to do a directory listing of that location, open up all the files and look for a specific event. You might use this to correlate events for forensic analysis, where something has happened and you have to track it’s course through the system. Ed then takes us on a rough guide of his blog, and it looks pretty. He mentions a profiling cmdlet called Measure-Command that is used to measure the performance of different commands in order to optimise different solutions. Questions and answers Q: Are there tools to convert Korn shell scripts to PowerShell scripts? A: No - not recommended because a Korn shell will be heavy on regular expressions for parsing text whereas PowerShell returns objects. Q: Can I reboot a remote server with PowerShell? A: Yes. There is a Stop-Computer and Restart-Computer cmdlet, so as long as you have connectivity and rights then you should be good. These commands take a list of computer names to use so you could reboot a list of computers. Q: What is the difference between a single quote and a double quote? A: A single quote(’) is a literal string and a double quote(") is an expanding string. The back-quote character (`) delimits the dollar and turns it into a normal character. Back-quote does the work of the back-slash in every other language I’ve come across.
$a=13 echo ‘a=$a’ a=$a echo “a=$a” a=69 echo “a=`$a” a=$a echo “number ‘$a’ is lucky for some” number ‘13′ is lucky for someQ: How can I sort a column after selecting? A: Pipe it to the Sort-Object cmdlet specifying the column you wish to sort on. You can use the -Descending to change the order.
Get-Process | Sort-Object processnameQ: Can you cache the event log in memory before filtering, would that be faster? A: You could read the entire event log into a variable and then you could do stuff. If you have lots of parsing and filtering then it could be faster. If you don’t have much to do then it’s much faster to do the filtering on the computer where the log sits. Q: Can I do everything with events viewer using the PowerShell cmdlet? A: Yes, if he was talking about doing everything in computer management then No. Q: Can you use the up arrow to bring up a multi-line command statement in one? A: No. Q: Can you use PowerShell to monitor events as they occur? A: Yes, there’s a whole series of articles on the HeyScriptingGuy site, mumble, mumble, mumble, look for the tag events, use can use WMI events or Windows events. [He just mumbled through the answer without saying anything coherent]. Q: Have you used Enter-PSSession and it’s related cmdlets? A: Of course, I have. Search the HeyScriptingGuy site with the tag of Remoting. Q: What is the difference between smooth brackets “()” and curly brackets “{}"? A: Smooth brackets are used as parameters coming into methods opener and closers whereas curly brackets are typically used for script blocks or code blocks. I can use “@(” to create an array and “@{” to create a hashtable. PowerShell array creation
$b = @("1″, “2″, “32″, “4″)
1 2 32 4PowerShell hashtable creation
$m = @{"a” = “1″} + @{"b"="2″}
Name Value ---- ----- a 1 b 2PowerShell subexpressions
$x = 10 echo $($x * 10) 100
No feedback yet
Form is loading...