March 10th, 2011

Use PowerShell to Find WMI Classes that Contain Methods

Summary: Learn how to use Windows PowerShell to find WMI classes that contain usable methods for making configuration changes in Windows.

Hey, Scripting Guy! Question  Hey, Scripting Guy! I that know you spend a lot of time working with WMI. The one thing that I really do not like about WMI is that although it seems like there is a lot of information that can be retrieved, it seems that there are not very many things that WMI can actually do. I guess what I am really interested in is: Are there WMI classes that have methods?

—SH

Hey, Scripting Guy! Answer Hello SH,

Microsoft Scripting Guy, Ed Wilson, here. It is less than a month until the 2011 Scripting Games, and things are really heating up. While I was in Seattle last week visiting with the Microsoft MVPs, I was able to round up a large number of judges and expert commentators. I have already begun emailing the events to the expert commentators, and I am compiling my list of judges. The judges and the judging criteria will be posted soon. The one location you need to bookmark is the 2011 Scripting Games: All Links on One Page site. Links to vital information will be presented throughout the next couple of months.

While sipping a cup of English Breakfast tea and munching a caramel flavored Tim Tam (provided by Microsoft MVP Shane Hoey from Australia), I finally had a chance to write a script I have been wanting to write for a long time. I had written a similar script for my Microsoft Press book, Windows Scripting with WMI, but I used VBScript for that endeavor, and I wanted to update it to Windows PowerShell.

One nice change in Windows PowerShell 2.0 is direct access to a methods collection. (In Windows PowerShell 1.0, it was more difficult to obtain this information.) One thing that makes the script a bit complicated is the way that WMI exposes information.

In the end, the Get-WmiClassMethods.ps1 script is a bit more complicated than I would like it to be, but it works and it accomplishes the job. Feel free to email improvements to the script to scripter@microsoft.com, or better yet, post a revision to the script to the Scripting Guys Script Repository so other scripters will have access to your work.

The complete Get-WmiClassMethods.ps1 script appears here:

Get-WmiClassMethods.ps1

# —————————————————————————–

# Script: Get-WmiClassMethods.ps1

# Author: ed wilson, msft

# Date: 03/08/2011 12:46:15

# Keywords: Scripting Techniques, WMI

# comments: Gets dynamic WMI classes that have methods marked with the implemented

# qualifier

# HSG-3-10-11

# —————————————————————————–

function New-Underline

{

<#

.Synopsis

 Creates an underline the length of the input string

.Example

 New-Underline -strIN “Hello world”

.Example

 New-Underline -strIn “Morgen welt” -char “-” -sColor “blue” -uColor “yellow”

.Example

 “this is a string” | New-Underline

.Notes

 NAME:

 AUTHOR: Ed Wilson

 LASTEDIT: 5/20/2009

 KEYWORDS:

.Link

 Http://www.ScriptingGuys.com

#>

[CmdletBinding()]

param(

      [Parameter(Mandatory = $true,Position = 0,valueFromPipeline=$true)]

      [string]

      $strIN,

      [string]

      $char = “=”,

      [string]

      $sColor = “Green”,

      [string]

      $uColor = “darkGreen”,

      [switch]

      $pipe

 ) #end param

 $strLine= $char * $strIn.length

 if(-not $pipe)

  {

   Write-Host -ForegroundColor $sColor $strIN

   Write-Host -ForegroundColor $uColor $strLine

  }

  Else

  {

  $strIn

  $strLine

  }

} #end new-underline function

 

Function Get-WmiClassMethods

{

 Param(

   [string]$namespace = “root\cimv2”,

   [string]$computer = “.”

)

 $abstract = $false

 $method = $null

 $classes = Get-WmiObject -List -Namespace $namespace | Where-Object { $_.methods }

 Foreach($class in $classes)

 {

  Foreach($q in $class.Qualifiers)

   { if ($q.name -eq ‘Abstract’) {$abstract = $true} }

  If(!$abstract)

    {

     Foreach($m in $class.methods)

      {

       Foreach($q in $m.qualifiers)

        {

         if($q.name -match “implemented”)

          {

            $method += $m.name + “`r`n”

          } #end if name

        } #end foreach q

      } #end foreach m

      if($method) {New-Underline $class.name}

      $method

    } #end if not abstract

  $abstract = $false

  $method = $null

 } #end foreach class

} #end function Get-WmiClassMethods

 

# *** Entry Point to Script ***

 

Get-WmiClassMethods

The first thing I do in the Get-WmiClassMethods.ps1 script is to create the New-Underline function. I wrote this standard function when I was writing all of the scripts for the Windows 7 Resource Kit. I have also used it in a number of Hey Scripting Guy! articles; therefore, I will not expound upon it here.

In the Get-WmiClassMethods function, I first create two input parameters. The first one is used for the WMI namespace, and the second one is for the computer name. Both are set to default parameters. I then initialize two variables that are used later in the function. This portion of the script is shown here.

Function Get-WmiClassMethods

{

Param(

[string]$namespace = “root\cimv2”,

[string]$computer = “.”

)

$abstract = $false

$method = $null

There are numerous WMI namespaces, and therefore the ability to change namespaces is an essential technique. In addition, the ability to run the script against a remote computer makes it a valuable tool because various versions of the operating system (and indeed various features and roles) provide access to different classes and namespaces.

By using the list parameter from the Get-WmiObject Windows PowerShell cmdlet, I am able to obtain a listing of all the WMI classes in a namespace. This listing contains abstract classes (that are not usable for scripting), in addition to classes that do not have methods. I use the Where-Object cmdlet to limit the results to only WMI classes that have methods. This list is stored in the variable $classes as shown here.

$classes = Get-WmiObject -List -Namespace $namespace | Where-Object { $_.methods }

Next I use the foreach statement to walk through the array of WMI classes. For each WMI class (stored in the $class variable) I look at the collection of qualifiers that are associated with the WMI class. If a WMI class has the abstract qualifier, I eliminate it from further consideration and I set the $abstract variable to $true. This portion of the script is shown here.

Foreach($class in $classes)

{

Foreach($q in $class.Qualifiers)

{ if ($q.name -eq ‘Abstract’) {$abstract = $true} }

If the $abstract variable is not set to $true, I proceed to obtain a collection of all of the methods that are associated with the WMI class (contained in the $class variable). To see if a method will work, I look for a qualifier named implemented. If the implemented qualifier exists, the method should work. If the method is not implemented, it will not work, and there is no point in returning it to my list. I then create a variable called $method to hold all of the implemented method names for each WMI class. This portion of the script is shown here.

If(!$abstract)

{

Foreach($m in $class.methods)

{

Foreach($q in $m.qualifiers)

{

if($q.name -match “implemented”)

{

$method += $m.name + “`r`n”

} #end if name

} #end foreach q

} #end foreach m

Now it is time to produce the report. I want to list only WMI class names that contain implemented methods. Therefore, I examine the $method variable to see if it contains any methods. If it does, I call the New-Underline function to underline the WMI class name, and I print the methods that are associated with the class.

Next, I need to clean out the $abstract and the $method variables so I can loop through the script for the next WMI class in the list. To call the script, I can use the function name (Get-WmiClassMethods) as I did here, or I can call the Get-WmiClassMethods function and pass a different computer and a different WMI namespace to it. This portion of the script is shown here.

if($method) {New-Underline $class.name}

$method

} #end if not abstract

$abstract = $false

$method = $null

} #end foreach class

} #end function Get-WmiClassMethods

# *** Entry Point to Script ***

Get-WmiClassMethods

When the script runs, the output that is shown in the following image appears.

Image of command output

Improvements to the script could be to add the ability to output to a file (redirection would work) and adding a progress indicator (the script takes several seconds to complete). For more information about WMI, refer to the Hey, Scripting Guy! blog.

SH, that is all there is to finding WMI classes that can actually do things. In Windows 7, there are some great new additions to WMI. I invite you to join me tomorrow when we will do a similar thing for properties. It will be really cool.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

 

Author

0 comments

Discussion are closed.