My first steps with PowerShell

I've been taking my first stumbling steps in PowerShell. I'm the contact here for the PowerShell user group and have been along to a couple of their meetings, and their enthusiasm is pretty infectious. PowerShell's really got some momentum behind it - having had a million downloads and a dozen or so books written for it (including the wonderful sounding Windows PowerShell. Sprachgrundlagen, Dateisystem, Datenbankzugriffe, WMI-Steuerung I think I to get learn the sprachgrundlagen myself)  I've done some programming over the years, and done some pretty advanced stuff with batch files. PowerShell is a new kind of beast for me.

Batch files are easy - commands from the command prompt , some basic if....then , for loops and so on. DOS copied the ideas of redirecting input and output from Unix you can redirect input to a text file from the keyboard  or redirect output from the screen to a text file.  You can miss out the text file and pipe the text emitted from one program into another. Whilst a batch file meets the fundamental definition of a "program" (a list of commands of the computer to execute), most people don't see producing batch files as programming. The most basic form of "real" programming is - well - Basic.

I've lost count of the number of BASICs I've programmed in: Micro-Soft BASIC was the second, in those days Micro and soft were separate words, and BASIC was an acronym for Beginners All-purpose Symbolic Instructional Code. 15 years ago Visual Basic was a whole new programming paradigm for a lot of people. Instead of having a program which ran from beginning to end (skipping some bits, and repeating others), we drew the user interface and then said what happened when a user did this or that with the controls. At the same time OLE-Automation, later COM and Active-X allowed us to manipulate complex entities as objects with methods (things they did) and properties (things they were). In the original BASIC you could have a variable X which was an array of text strings and that was as sophisticated as it got. Now you could say X was an instance of Internet Explorer, or a User in AD, or the results from a SQL query, the objects did the work and often VB's job was just to tie them together. VB script used the same syntax to do tasks with no GUI and a more linear flow.

A lot of IT professionals don't program - in the VB (script)  sense. And that rules out automating tasks, like setting an AD attribute for many users. Cue PowerShell. A 21st Century replacement for the "DOS box".  This much I understood months ago. I even understood that a lot of PowerShell commands (or Cmdlets as it calls them) are in the format Verb-noun, like "GET-HELP" - which gives  information the others. What I'm going to do is show you how I did my first little scrap of PowerShell and if you haven't used it you might get some ideas about it's power.

At last weeks PowerShell user group on of the presenters was showing what could be done with the "GET-WMIobject" cmdlet. So the the first thing I did was try GET-HELP Get-WMIobject -full (without -full we get a brief summary) .   A quick skim of the help tells me that GET-WMIOBJECT -LIST will tell you what the classes of object you can get to via WMI - when you know what you want GET-WMIobject -class [classname]  the object(s) so I'm going to see what QFEs (Hot fixes) my machine has - (I've shortened the results a bit) 

 PS C:\Users\Jamesone> Get-WmiObject -Class win32_quickfixengineering 
Description         : Update
FixComments         :
HotFixID            : KB932246
Install Date        :
InstalledBy         : S-1-5-18
InstalledOn         : 01c7750dbf25f258
Name                :
ServicePackInEffect :
Status              : 
 Description         : Update
FixComments         :
HotFixID            : KB936824
Install Date        :
InstalledBy         : S-1-5-18
InstalledOn         : 01c79da8934e128a
Name                :
ServicePackInEffect :
Status              :

I can see what's there, but it's not that helpful. There is already a bit of magic going on because PowerShell has figured out how to output text from an array of objects - VB would have needed a few lines of code to do that. But now what can I do with these objects ? At this point I usually need the object browser in an interactive development environment. With Powershell I can Pipe objects into other cmdlets. Oooh....that's interesting... one of the commands is get-member which lists and object's properties and methods

 PS C:\Users\Jamesone> Get-WmiObject -Class win32_quickfixengineering | get-member 
    TypeName: System.Management.ManagementObject#root\cimv2\Win32_QuickFixEngineering 
  Name                MemberType   Definition
----                ----------   ----------
Caption             Property     System.String Caption {get;set;}
CSName              Property     System.String CSName {get;set;}
Description         Property     System.String Description {get;set;}
FixComments         Property     System.String FixComments {get;set;}
HotFixID            Property     System.String HotFixID {get;set;}
InstallDate         Property     System.String InstallDate {get;set;}
InstalledBy         Property     System.String InstalledBy {get;set;}
InstalledOn         Property     System.String InstalledOn {get;set;}
Name                Property     System.String Name {get;set;}
ServicePackInEffect Property     System.String ServicePackInEffect {get;set;}
Status              Property     System.String Status {get;set;}
__CLASS             Property     System.String __CLASS {get;set;}
__DERIVATION        Property     System.String[] __DERIVATION {get;set;}
__DYNASTY           Property     System.String __DYNASTY {get;set;}
__GENUS             Property     System.Int32 __GENUS {get;set;}
__NAMESPACE         Property     System.String __NAMESPACE {get;set;}
__PATH              Property     System.String __PATH {get;set;}
__PROPERTY_COUNT    Property     System.Int32 __PROPERTY_COUNT {get;set;}
__RELPATH           Property     System.String __RELPATH {get;set;}
__SERVER            Property     System.String __SERVER {get;set;}
__SUPERCLASS        Property     System.String __SUPERCLASS {get;set;}
PSStatus            PropertySet  PSStatus {__PATH, Status}
ConvertFromDateTime ScriptMethod System.Object ConvertFromDateTime();
ConvertToDateTime   ScriptMethod System.Object ConvertToDateTime();
Delete              ScriptMethod System.Object Delete();
GetType             ScriptMethod System.Object GetType();
Put                 ScriptMethod System.Object Put(); 

I'm only interested in HotfixID and  Description Properties and PowerShell has a format-table cmdlet to present them nicely.

 PS C:\Users\Jamesone> Get-WmiObject -Class win32_quickfixengineering | format-Table Hotfixid, description 
Hotfixid                                                    description
--------                                                    -----------

KB929399                                                    Update
KB929451                                                    Hotfix

KB930163                                                    Update
KB930178                                                    Security Update
KB930857                                                    Update
KB925902                                                    Security Update
KB931573                                                    Update
KB931768                                                    Security Update

 

The second half of that line tells PowerShell "I'm going to throw some objects your way: pull out the hotfix-ID and description properties and format them nicely." Two things leap out here: first I can format text in VB but this is much quicker. And secondly the "Incoming object! - use these properties " approach. Suppose I only want the Security updates - rather than figuring out how to use get-wmiObject's -query switch I could use the Where-object cmdlet. Since I don't know anything about how it works I need  to GET-HELP for it; with a -full switch it includes:

 -------------------------- EXAMPLE 1 -------------------------- 
C:\PS>get-service | where-object {$_.Status -eq "Stopped"} 
This command gets a list of all services that are currently stopped. 

There's some syntax I have to work out here: $_ for "the current one" and -eq for equals  but anyone can swap .status -eq "Stopped"  over to be  .description -eq "Security update". So I'll insert that.

 PS C:\Users\Jamesone> Get-WmiObject -Class win32_quickfixengineering | where-Object {$_.description -eq "Security Update"} | format-table hotfixId, description 
hotfixId                                                    description
--------                                                    -----------
KB930178                                                    Security Update
KB925902                                                    Security Update
KB931768                                                    Security Update 

Of course it would be better if they were sorted into order. Another quick look at the help says I can pipe my results to sort-Object hotfixid

 PS C:\Users\Jamesone> Get-WmiObject -Class win32_quickfixengineering | where-Object {$_.description -eq "Security Update"} | sort-object hotfixID | format-table hotfixId, description 
hotfixId                                                    description
--------                                                    -----------
KB925902                                                    Security Update
KB930178                                                    Security Update
KB931768                                                    Security Update 

It's taken me about 10 times longer to write the blog post than to get to the command line that will do all this for me. PowerShell can't do everything it's ability to call out to .net or COM objects or WMI means it can do a huge amount.  And it opens it up to those who don't program - and lets established programmers get a result more quickly. More importantly when we say things like "PowerShell is part of better management in Longhorn" this is what we're talking about. It also means when we say "there are more WMI providers" mere mortals can do something with them. I can see I'm going to be doing more with this technology.

 

Technorati tags: Microsoft, Windows, powershell