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