PowerShell for Windows Admins

March 23, 2014  4:51 AM

Discovering CIM/WMI methods and parameters

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

As you’ve probably gathered I spend a lot of time working with, and investigating, CIM (WMI) classes. CIM and WMI will be treated as synonymous for these articles.

If you want to discover the methods available on a CIM class you can do this:

$class = Get-CimClass -ClassName Win32_Process


If you want to drill down into an individual method you then have to do this:


We end up with a two stage process. Firstly discover the available a methods and then discover the parameters on the method.

In a busy session this can turn into a lot of typing. You can short-circuit some that if you using the Get-CimMethodParameter from the CIM Utilities modules that can be downloaded from http://gallery.technet.microsoft.com/scriptcenter/CimUtilities-56d9dd99

To my mind it only supplies an answer to the last part of the problem. There is a hidden method – Get-CimMethod – that does the first step but as its not published it doesn’t help us.

I decided that its time to re-write the module to work the way I want. This provides an opportunity to go over the functionality of Get-CimClass, Advanced functions and modules.

To define my problem:

I want a cmdlet that:

provides a list of methods on a WMI class

provides the parameters of a specific method

the standard output of Get-CimClass is acceptable

work with any namespace

work with remote machines

not concerned about pipeline input at this stage (may add later)

not concerned about outputting parameters as a hash table ( though may add later)

I’ll start with a simple function to perform the first two requirements.

function Get-CimMethod {


param (




if ($methodname)


$class = Get-CimClass -ClassName $classname





Get-CimClass -ClassName $classname | select -ExpandProperty CimClassMethods



I decided to save this as a psm1 file (module file) and called the module CimInvestigation.

In PowerShell 3 & 4 the module autoloads so I can do this:

Get-CimMethod -classname Win32_NetworkAdapter

Get-CimMethod -classname Win32_NetworkAdapter -methodname setpowerstate

Next time I’ll turn this into more of an advanced function with some validation and error checking

March 21, 2014  12:39 PM

DSC, Windows 2012 R2 and GA

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Windows 2012 R2 GA (General Availability) occurred in October 2013. Downloads of the Windows 2012 R2 RTM release were made available on MSDN before that time however there were some changes made between RTM and GA that have a significant impact on Desired State Configuration – it breaks on most code you will find.

The answer is to install some updates.

As an absolute bare minimum you should install the GA update – KB2883200 (Note that KB 2894029 and KB 2894179  are included in the KB2883200 download)



When you install Windows 2012 R2 check that KB2883200 has bee installed. If not download and install.

I’d also recommend that you install KB2884846 (you also get KB2898742) – the October 2013 update rollup.



There is also a March 2014 update rollup –  KB2928680 – this important because it fixes the AD cmdlet issue



If you want to get the best out of Windows 2012 R2 make sure you install these updates. Matching updates are available for Windows 8.1 as well.

March 20, 2014  12:36 PM

Where’s the value

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

PowerShell is object based – its the one fact that is mentioned in very introduction to PowerShell – and its the use of objects that gives PowerShell its reach and power.

The use of objects has one tiny drawback. When you want the actual value of a property you have to do slightly more work.

This is representative of a typical PowerShell expression

£> Get-Process powershell | select Path




Now if you want the value of path itself to use elsewhere you have to do one of three things:

£> $proc = Get-Process powershell

£> $proc.Path



£> $path = Get-Process powershell | select -ExpandProperty Path

£> $path



£> $proc = (Get-Process powershell | select Path).path

£> $path


The first one gives you an object to work with. If you want other properties you can access them later.

The other two options give you a variable containing just the information you need – the value of the Path property.

Which one works best – depends on what you are doing. I use all three techniques on a regular basis though tend to prefer using option 2 to option 3 – mainly because I find it easier to read when I come back to the script weeks, months or even years later.

March 19, 2014  8:33 AM

Give me a break

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Having shown how to use continue last time I thought I’d show the opposite functionality this time and demonstrate how to jump out of a loop.

You do this using the break command.  The following examples show how it works. What do you think the output of these loops will be?

FOR loop

for ($i=1; $i -le 6; $i++){   if ($i -eq 4) {break}   $i }

WHILE loop

$i = 0 while ($i -lt 6){ $i++ if ($i -eq 4) {break} $i

DO loop

$i = 0 do { $i++ if ($i -eq 4) {break} $i } while ($i -lt 6)

$i = 0 do { $i++ if ($i -eq 4) {break} $i } until ($i -ge 6)


$numbers = 1..6 foreach ($number in $numbers) { if ($number -eq 4) {break} $number }

If you said the output would be




You were correct.


1..6 | foreach { if ($psitem -eq 4) {break} $psitem }

Though you want to think carefully before terminating a pipeline like this.

March 18, 2014  3:34 PM

Continue please

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I needed to be able to skip processing in a loop and remembered that the continue command suspends the loop processing and immediate goes back to the top of the loop. I thought a quick look at how it works in different types of loop would be worthwhile.

These all work and produce the same output






FOR loop

for ($i=1; $i -le 6; $i++){

if ($i -eq 4) {continue}



WHILE loop

$i = 0

while ($i -lt 6){


if ($i -eq 4) {continue}



DO loop

$i = 0

do {


if ($i -eq 4) {continue}


} while ($i -lt 6)

$i = 0

do {


if ($i -eq 4) {continue}


} until ($i -ge 6)


$numbers = 1..6

foreach ($number in $numbers) {

if ($number -eq 4) {continue}




1..6 |

foreach {

if ($psitem -eq 4) {continue}



You will terminate the pipeline by using continue.

One way to do this would be:

1..6 |

foreach {

if ($psitem -ne 4) {$psitem}


Continue is a useful trick that gives you more control within the loop

March 18, 2014  1:05 PM

WMI type accelerators

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Something you don’t see used very often but that you need to be aware of are the WMI type accelerators. These were introduced as part of PowerShell 1.0 and have continued to be available in later versions.

A type accelerator is a shortcut to using a .NET class – remember everything in PowerShell is >NET based – even WMI.  There are three accelerators:



This is the same as

Get-WmiObject -Class Win32_Process -Filter “Handle=5028”


Get-CimInstance -ClassName Win32_Process -Filter “Handle=5028”

The draw back is that you have to use the WMI class Key which is Handle in Win32_Process. Get-WmiObject and Get-CimInstance give you a wider set of filtering options – the –Filter parameter will work on most properties


This provides a shortcut for creating new instances:

$p = [wmiclass]’Win32_Process’ $p.Create(“calc.exe”)

This was your only option in PowerShell 1.0 for accessing the Create method. With PowerShell 2.0 and 3.0 these options were added respectively:

Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList ‘calc.exe’

Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{CommandLine=’calc.exe’}


The final WMI type accelerator can be used to find WMI data. You need to use a WQL query

$query = [wmisearcher]”SELECT * FROM Win32_Process WHERE Name=’calc.exe'” $query.Get()

Your alternatives are:

Get-WmiObject -Query “SELECT * FROM Win32_Process WHERE Name=’calc.exe'”

Get-CimInstance -Query “SELECT * FROM Win32_Process WHERE Name=’calc.exe'”

OR better still

Get-WmiObject -Class Win32_Process -Filter “Name=’calc.exe'”

Get-CimInstance -ClassName Win32_Process -Filter “Name=’calc.exe'”

Lots of choices and one of these techniques will solve your problem when working with WMI.  More information is available in Chapter 3 of PowerShell and WMI – www.manning/siddaway2

March 17, 2014  12:57 PM

Multiple book offers

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

There are multiple money off offers from Manning for you to consider.

Firstly – tomorrow March 18 2014: Half off Learn Active Directory Management in a Month of Lunches. Use code dotd031814au at www.manning.com/siddaway3/

The deal will go live at Midnight US ET and will stay active for ~48 hours.

Some other books in the Month of Lunches series will also be available under this offer.

Secondly – PowerShell in Depth 2E is going on to Early Access – http://www.manning.com/jones6/ You can get 50% off using code –  pid2eco

It is valid for the MEAP, eBook and pBook.  The code will be active until March 20.

Yes, we updated PowerShell in Depth for PowerShell v4.  Every chapter has been examined and brought up to date with v4 material added as appropriate. We have also added chapters including one on Desired State Configuration.

Thirdly there is a 45% of everything offer! Just enter wm031714 in the Promotional Code box when you check out. Offer applies to your entire purchase–eBook, pBook, or MEAP. Expires March 25.

Now would be a good time to get those books you’ve promising yourself

March 16, 2014  10:15 AM

Select is a filter

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

This is a common scenario:

Get-WmiObject -Class Win32_Logicaldisk | select Name, Size, Freespace

You will see a display with three properties – turning them into a list for ease of display:

Name      : C: Size      : 248951861248 Freespace : 171627724800

What this means is that you’ve got an object with 3 properties.

£> Get-WmiObject -Class Win32_Logicaldisk | select Name, Size, Freespace | Get-Member

TypeName: Selected.System.Management.ManagementObject

Name        MemberType   Definition

—-        ———-   ———-

Equals      Method       bool Equals(System.Object obj)

GetHashCode Method       int GetHashCode()

GetType     Method       type GetType()

ToString    Method       string ToString()

Freespace   NoteProperty System.UInt64

Freespace=171627569152 Name       

NoteProperty System.String Name=C: Size       

NoteProperty System.UInt64 Size=248951861248

The object type changes – its now a Selected.System.Management.ManagementObject rather than System.Management.ManagementObject#root\cimv2\Win32_LogicalDisk you get from WMI.

Try this to see the whole list of properties

Get-WmiObject -Class Win32_Logicaldisk | Get-Member

Select-Object is great because you can trim down the size of the objects on your pipeline but you have to remember that once you performed that selection its a one way street you can’t get back to the original.

If you need to perform multiple actions on the objects put them into a variable:

$disks = Get-WmiObject -Class Win32_Logicaldisk

then you can do:

$disks | <pipeline 1>

$disks | <pipeline 2>


foreach ($disk in $disks) { <do stuff to the disks>}

Where and when to filter you data using Where-Object or Select-Object is part of your design process and only you know what works in your situation. The rule of thumb is filter early to reduce the data on the pipeline but knowing when to break that rule is what makes or breaks your solution

March 16, 2014  5:37 AM

Learn Active Directory Management in a MoL on offer

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Learn Active Directory Management in a MoL is 43% off through April 3, 2014 with code pbradm at www.manning.com/siddaway3/

March 15, 2014  4:48 AM

Module confusion–what’s really in PowerShell 3 and 4

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

If I run

Get-Module –ListAvailable

on my Windows 8.1 system (PowerShell 4.0) I find a total of 58 modules installed in $pshome\modules i.e. C:\windows\system32\WindowsPowerShell\v1.0\Modules

These are the modules installed as part of PowerShell. Right?


Compare this with a Windows 7 machine that’s been upgraded to PowerShell 4.0. Repeating the exercise I find a grand total of 15 modules.

So where has the other 75% of my functionality gone.

This is the breakdown down of the modules installed on the Windows 7 machine – terminology is mine (feel free to disagree with the groupings).

Core PowerShell:









File Transfer module





Other related engines:





and that’s it. Everything else as far as I can determine is CDXML based and therefore can’t be made available on legacy systems. The following modules are included in that category:












































A CDXML based module is produced by taking a CIM (WMI) class and wrapping it in some simple XML and saving it as a .cdxml file. This can then be published as a PowerShell module. The CIM classes won’t be made available on downlevel systems so you won’t find this functionality on anything earlier than Windows 8/2012.

If you need the functionality supplied by these modules you will either have to use the old command line tools or a WMI class – much of the functionality of the NetAdapter and NETCPIP modules for instance can be duplicated using Win32_NetworkAdapter and Win32_NetworkAdapterConfiguration..

Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to: