Thursday, August 21, 2008

PowerShell and COM

I mentioned to a few people today that you can use PowerShell to create COM objects, but I think that warrants a little explaining.  VBScript automation examples use COM a lot, and if you're going to want to use PowerShell to automate Word documents or any of that other neat stuff, you'll need to use it as well.  

Consider the code below:

PS C:\> $sms_client = New-Object -COM 'CPApplet.CPAppletMgr'             #1
PS C:\> $sms_client | gm                                                 #2


   TypeName: System.__ComObject#{279463bb-1034-4fb5-878e-4a330a08beab}

Name                MemberType Definition
----                ---------- ----------
GetClientActions    Method     IClientActions GetClientActions ()
GetClientComponents Method     IClientComponents GetClientComponents ()
GetClientProperties Method     IClientProperties GetClientProperties ()

PS C:\> $actions = $sms_client.GetClientActions()                        #3
PS C:\> $actions | select Name                                           #4

Name
----
Software Inventory Collection Cycle
MSI Product Source Update Cycle
Hardware Inventory Collection Cycle
Standard File Collection Cycle
Discovery Data Collection Cycle
Request & Evaluate User Policy
Request & Evaluate Machine Policy
Software Metering Usage Report Cycle

PS C:\> $machine_policy = $actions | ?{$_.Name -like "*Machine Policy"}  #5
PS C:\> $machine_policy.PerformAction()                                  #6

In the code above, "CPApplet.CPappletMgr" is the name of the COM type that is equivalent tot he Systems Management applet in the control panel, so here's what the code does:

  1. Creates a new COM object of type 'CPApplet.CPAppletMgr'.  This is the equivalent of "sms_client = CreateObject('CPApplet.CPAppletMgr')" in VBScript.
  2. Runs Get-Member (gm) on the variable I just set to see what methods are available.
  3. Calls the GetClientActions method and stores the resulting array in $actions.
  4. Uses Select-Object (select) to get just the names of each action
  5. Uses Where-Object (?) to get just the action whose name is like "*Machine Policy" and assign it to $machine_policy
  6. Invokes the PerformAction() method of $machine_policy.

Worthy of note is that piping to where technically creates a one-element array, but PowerShell automatically converts that to a scalar by default, so I didn't have to use $machine_policy[0].  If I had actually wanted it to be treated as an array (let's say I'll be using the .Length() method of an array to see how many items were returned, I would have to use the @() syntax to force it:

PS C:\> $machine_policy = @($actions | ?{$_.Name -like "*Machine Policy"}) 

No comments: