A PowerShell WMI Helper Module Described

Summary: In this article, Microsoft Scripting Guy Ed Wilson begins part 1 of a multipart WMI helper function module for Windows PowerShell.


Microsoft Scripting Guy Ed Wilson here. While I was teaching my Windows PowerShell Best Practices class in Montreal, we spent an entire day talking about Windows Management Instrumentation (WMI). While WMI seems to have a “bad reputation” in terms of complexity, consistency, and discoverability, Windows PowerShell has done much to make WMI more consistent, less complex, and definitely more discoverable. Personally, I love WMI not only because it provides ready access to reams of documentation about my computer systems, but also because it exposes many methods and writable properties that allow me to quickly and accurately configure many aspects of my systems. Ever since I began working on my Windows PowerShell Step By Step book for Microsoft Press, I have written hundreds of WMI scripts and helper functions. This week, I am going to collect together many of the helper functions into a single module that will make access to WMI information easier.

The first function I add to my WMI module is the Get-WMIClassesWithQualifiers function that I wrote for the Use a PowerShell Function to Find Specific WMI Classes post last Saturday. See that article for details on the function.

Creating a Windows PowerShell module is really easy. I open the Windows PowerShell ISE and paste my Get-WMIClassesWithQualifiers function into the script pane. This technique is shown in the following figure.

Image of technique to create module

After I have pasted the first function into the module, I need to save the module so that I do not lose my work. I save the module into my scratch directory (called FSO off the root drive), giving me a place to work. After I have completed the module, I will use my Copy-Modules function to install the module into my user module location. The key thing to remember when saving a module is that the file extension must be .psm1. By default, the Windows PowerShell ISE saves files with a .ps1 extension, which is a Windows PowerShell script. A .psm1 file extension indicates a Windows PowerShell module. This technique is shown in the following figure.

Image of saving module with .psm1 extension

I decided that I would also like to include the Get-WmiClassMethods function and the Get-WMIClassProperties functions in my WMI module. The great thing about these two functions is that they make it really easy to find methods and properties that are implemented and writable. This is really important! Because of the way that the Get-Member cmdlet works, it shows everything in WMI as read/write. And though this is technically correct (at least to a point in that I can update an object in memory), it is of very little practical value because I cannot update all WMI objects. For example, if I use the Get-Member cmdlet on the Win32_LogicalDisk WMI class, it reports that all of the properties are Get/Set. Obviously, I cannot use WMI to change the size of my disk drive, and I am not certain I want to attempt to change the amount of free space on my drive by using WMI. This is shown in the following figure.

Image of running Get-Member on Win32_LogicalDisk WMI class

Therefore, I need a better methodology for obtaining this information. I can use the Windows Management Instrumentation Tester (WbemTest) tool, but unfortunately, it requires me to examine every property in an individual manner to discover if a property is writable. This is not an acceptable solution when attempting to do a bit of quick scripting work.

Back in March of 2011, I wrote a series of Hey, Scripting Guy! posts where I explored writable WMI properties and implemented WMI methods. I decided to adapt those scripts to meet the need of my HSGWMIModule. The original script from March 12, 2011, is shown on the Scripting Guys Script Repository. I uploaded the modified functions to the Scripting Guys Script Repository so that you will have them if you wish to follow along.

I made the following changes to the original functions:

  1. It no longer checks for all WMI classes in a particular namespace. Instead, I have limited the scope to a single class.
  2. I made the $class parameter a mandatory parameter. You must supply a WMI class name to use the modules.
  3. I added comment-based help, and included examples of use.
  4. I changed the default computer name from “.” to $env:computername so that an actual computer name is used.
  5. I perform a [wmiclass] cast of the string supplied to $class so that it converts the string into a management object. This precludes the use of the Get-WmiObject cmdlet to return management objects.
  6. I removed the “entry” to the script, so running the script loads the functions into memory, but does not execute any searches.

So I have added the newly revised modules to my HSGWMIModule. I import the module from my scratch location, and use the Get-Command cmdlet (gcm is alias) to see the names of the functions contained in the module. Here are the commands and associated results:

PS C:\Users\edwils> Import-Module C:\fso\HSGWMImodule.psm1

PS C:\Users\edwils> gcm -Module hsg* | select name







The complete HSGWMIModuleV1 appears on the Scripting Guys Script Repository. You should download it, install it, and play with it. It is 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