Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to simplify collecting information from multiple Windows PowerShell cmdlets.
Microsoft Scripting Guy, Ed Wilson, is here. This morning, it is cool and crisp outside. I decided to make a pot of English breakfast, but I also put a spoonful of Darjeeling tea in it. Together with some lemon pith, a cinnamon stick, and a half spoon of Lavender, I have a very refreshing cup of tea to accompany me to the lanai.
Note Last week I wrote a three-part series that talked about Windows PowerShell objects, which have information related to today’s post:
- In A PowerShell Object Lesson: Part 1, I talked about the advantage of using Windows PowerShell objects, and how they are helpful to the scripter.
- In A PowerShell Object Lesson: Part 2, I talked about pipelining objects.
- In A PowerShell Object Lesson: Part 3, I talked about various ways to create objects.
Collect information from multiple PowerShell cmdlets
One of the really cool things about Windows PowerShell is how easy it makes it to collect lots of useful information. For instance, when I begin to troubleshoot a computer, I look at the system and application event logs. Generally, in that order. I also look at processes and services. For this initial look, however, I do not want to look at all the events, I usually only look at the first few events. Also, for the initial look, I only look at running services. Later, I look for automatic starting services that are not running, but I do not do that initially.
I decided to put these four commands into a simple script, and to return a custom object with the collection of information. This makes it easy to get all the information, but it does not clutter stuff when I am going through the output. It is actually a pretty cool technique. Here is the script:
# CombineDotNetObjects.ps1
# ed wilson, msft
# hsg-11-13-13
# -----------------------------------------------------------------------------
$app = Get-EventLog -LogName application -Newest 5
$sys = Get-EventLog -LogName System -Newest 5
$proc = Get-Process
$serv = Get-Service | where status -eq 'running'
$object = [pscustomobject]@{
Applog = $app
SysLog = $sys
Process = $proc
Service = $serv}
$object
Now for the shocker
So I have this really cool script, but the output from the script is probably not what one might expect. In fact, when I talk to newbies about Windows PowerShell, generally one of the first things that comes up when dealing with objects is what to do when a property of an object contains other objects. This is, in fact the beauty of this technique. My custom object is simply a repository that holds the objects that returned from the earlier commands. So it is an object that is itself a collection of other objects. When I run the script, the output is less than impressive:
Less than impressive? In fact, the output is downright useless. But remember, that each property contains other objects. So I can use the $object object to access the objects stored in each property. For instance, here are the five application logs:
PS C:\> $object.Applog
Index Time EntryType Source InstanceID Message
----- ---- --------- ------ ---------- -------
6002 Oct 29 14:49 Information Microsoft-Windows... 2003 The Windows Location Provider has successfully shutdown
6001 Oct 29 14:48 Information Microsoft-Windows... 2001 The Windows Location Provider has successfully started
6000 Oct 29 14:48 Information LocationNotificat... 1 A program accessed information from a location sensor o...
5999 Oct 29 14:44 Information Microsoft-Windows... 2003 The Windows Location Provider has successfully shutdown
5998 Oct 29 14:41 Information Microsoft-Windows... 2001 The Windows Location Provider has successfully started
Here are the five system logs:
PS C:\> $object.SysLog
Index Time EntryType Source InstanceID Message
----- ---- --------- ------ ---------- -------
10114 Oct 29 15:03 Warning Microsoft-Windows... 8020 The system failed to register host (A or AAAA) resource...
10113 Oct 29 15:03 Warning Microsoft-Windows... 1014 Name resolution for the name edlt.iammred.net timed out...
10112 Oct 29 15:02 Error NETLOGON 5719 This computer was not able to set up a secure session w...
10111 Oct 29 14:33 Warning Microsoft-Windows... 8020 The system failed to register host (A or AAAA) resource...
10110 Oct 29 14:33 Warning Microsoft-Windows... 1014 Name resolution for the name edlt.iammred.net timed out...
When I access the Process property from the object, the output is exactly the same as would have been produced by the Get-Process cmdlet. Here is the command and the output:
I get the same sort of output from the Service property, as shown here:
Now, I could add a bit of additional script, and unravel all of the objects to the Windows PowerShell console when the script runs. But at that point, it is the same as running the four commands and not storing them in variables, but storing them in a custom object.
The big advantage comes from the fact that all the commands run at essentially the same time, so my object becomes a snapshot in time. I then have the opportunity to peruse the data in the stored objects and compare results from one to the other. This technique promotes interactive analysis and discovery.
That is all there is to using Windows PowerShell objects. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy