header image

Archive for Deep Dive

WMI classes will sometimes have be associated with other classes for example each instance of the Win32_NetworkAdatper class is associated with an instance of the Win32_NetworkAdapterConfiguration.  The link is expressed by the Win32_NetworkAdapterSetting which shows the links.

I normally use WQL queries based on ASSOCIATORS and REFERENCES to discover these classes.  ASSOCIATORS shows the end point of the link and REFERENCES shows the linking class

We can do some of this work directly from the WMI object.

Lets get a network adapter object (you will need to use a deviceid thats present on your machine)

$nic = Get-WmiObject Win32_NetworkAdapter  -Filter "DeviceId=11"

and check its methods

$nic | gm -MemberType method


This doesn’t show what we need so we’ll drop to the underlying object

$nic.psbase | gm -MemberType method


which shows two methods of interest



We could also use

$nic | gm -MemberType method -View base

The methods relate to WQL like this

GetRelated = Associations
GetRelationships = References


What we get with these methods is the full related object.  We don’t have a method on the object to discover the classes that are related. For that we stick with WQL

Get-WmiObject -Query "ASSOCIATORS OF {Win32_NetworkAdapter.DeviceID=11} WHERE ClassDefsOnly"
Get-WmiObject -Query "REFERENCES OF {Win32_NetworkAdapter.DeviceID=11} WHERE ClassDefsOnly"


though these snippets are equivalent

$nic.GetRelated() | select __class –Unique

$nic.GetRelationships() | select __class –Unique


If we want to see the associated classes we can do this



Get-WmiObject -Query "ASSOCIATORS OF {Win32_NetworkAdapter.DeviceID=11}"


For a specific result class we can do this



et-WmiObject -Query "ASSOCIATORS OF {Win32_NetworkAdapter.DeviceID=11} WHERE ResultClass=Win32_NetworkAdapterConfiguration"


Switching to the links between classes – if we want to see all the links



Get-WmiObject -Query "REFERENCES OF {Win32_NetworkAdapter.DeviceID=11} "


and if we want to see a single link



Get-WmiObject -Query "REFERENCES OF {Win32_NetworkAdapter.DeviceID=11} WHERE ResultClass=Win32_NetworkAdapterSetting"

This gives us two routes to the information we need.  Use whichever you are most comfortable with.

under: Deep Dive, PowerShell and WMI

During Jeff Hicks’ talk about formatting he did the usual demo of taking an extract of a format file and modify it to create a new default format. 

Jim Truher mentioned that he had a script that would generate the XML for a format file and that he would post it.  He has and its here



If you want to modify the way things are displayed or create you own standard formats this will make life much easier.

under: Deep Dive, PowerShellV2

One topic that came up during my talk at Deep Dive was the speed of running a WQL vs using –Filter in Get-WmiObject.  I’d never tested it so its time to find out.

PowerShell v2 has a handy cmdlet called Measure-Command that times how long a command runs

We’ll start with using a filter

Get-WmiObject -Class Win32_Process -Filter "Name=’Notepad.exe’"


if we wrap it in Measure-Command we get this

Measure-Command -Expression {Get-WmiObject -Class Win32_Process -Filter "Name=’Notepad.exe’"}

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 81
Ticks             : 817436
TotalDays         : 9.46106481481481E-07
TotalHours        : 2.27065555555556E-05
TotalMinutes      : 0.00136239333333333
TotalSeconds      : 0.0817436
TotalMilliseconds : 81.7436


We want the TotalMilliseconds property and we need to do it more than once


1..100 | foreach {Measure-Command -Expression {Get-WmiObject -Class Win32_Process -Filter "Name=’Notepad.exe’"}} |

Measure-Object -Property TotalMilliseconds -Average

Count    : 100
Average  : 52.640332
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds


Now lets repeat as a query

Get-WmiObject -Query "SELECT * FROM Win32_Process WHERE Name=’Notepad.exe’"


which becomes

Measure-Command -Expression {Get-WmiObject -Query "SELECT * FROM Win32_Process WHERE Name=’Notepad.exe’"}


1..100 | foreach {Measure-Command -Expression {Get-WmiObject -Query "SELECT * FROM Win32_Process WHERE Name=’Notepad.exe’"}} |

Measure-Object -Property TotalMilliseconds -Average

Count    : 100
Average  : 52.345972
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds


Just for fun lets try this

1..100 | foreach {Measure-Command -Expression {Get-WmiObject -Class Win32_Process | Where {$_.Name -eq ‘Notepad.exe’} }} |

Measure-Object -Property TotalMilliseconds -Average

Count    : 100
Average  : 92.96794
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds


So the results so far

Filter:  52.640332

Query:   52.345972

Where:   92.96794

The filter and the query are almost the same – I’m not going to argue over 0.03 milliseconds.  Using Where-Object takes nearly twice as long. This is understandable because the query and filter pick out a single process but using Where-Object we return all processes and then filter.

I stated in my talk that it was better to use the filter because it was less typing. On these results I’ll stand by that statement for local machines as it takes me more than a few milliseconds to type the extra characters using a query.

Further research is needed:

  1. What happens if running against remote machines?
  2. is it faster to select properties in the query or using select-object

We’ll return to these points later

under: Deep Dive, PowerShell and WMI

One question that I was asked at the deep dive –

Is there a way to link a disk volume back to the physical disk it resides on?

There doesn’t seem to be. If we test the WMI classes associated with a volume we get these results


If anyone knows how to relate Win32_Volume to the physical disk (need to get the serial number off the disk) then I’d be interested in hearing about it

under: Deep Dive, PowerShellV2

The PowerShell Deep Dive last week was the best conference I have ever attended. The group consisted of members of the PowerShell team, Ed Wilson – the Scripting Guy, PowerShell MVPs and a large number of PowerShell experts and enthusiasts.  The last word summed it up.  The Scripting Club was supposed to finish at 10pm – it really finished at 3am next morning.

The sessions were short – 35 minutes – and much more interactive than a normal conference. A blog post can’t do justice to the event all I can say is that I’ll be booking for the next one as soon as its announced.

With that many experts drawn together I managed to learn something in every session – even the one I gave!

I’ll post some snippets of I what I learned in a series of posts. Some you may know & some may be new.

The first snippet involves working with COM collections. Many COM objects have properties that are actually collections of other objects. As an example consider the Windows firewall.

$fw = New-Object -ComObject HNetCfg.FwMgr

If we drill into the object we find


on my machine I get three services

– File and Printer Sharing
– Network Discovery
– Remote Desktop

The logical thing to try would be

PS> $fw.LocalPolicy.CurrentProfile.Services[0]
Unable to index into an object of type System.__ComObject.
At line:1 char:41
+ $fw.LocalPolicy.CurrentProfile.Services[ <<<< 0]
    + CategoryInfo          : InvalidOperation: (0:Int32) [], RuntimeException
    + FullyQualifiedErrorId : CannotIndex


But we get an error.  The collection doesn’t have an index.  Bah!!!

But if we do this

$x = @($fw.LocalPolicy.CurrentProfile.Services)


we can then do this

PS> $x[0]

Name              : File and Printer Sharing
Type              : 0
Customized        : False
IpVersion         : 2
Scope             : 1
RemoteAddresses   : LocalSubnet
Enabled           : True
GloballyOpenPorts : System.__ComObject


which gives us an array where we can work with indexes

Simple but effective.

This is one of the strengths of an event like Deep Dive – you get to pick everyone else’s brain. During a session someone said “None of us know it all but between us in this room we know nearly all of it”

That should be the motto of the PowerShell community!!

under: Deep Dive, PowerShellV2

« Newer Posts