July 16th, 2013

Query Multiple WMI Classes but Return One Object with PowerShell

Doctor Scripto
Scripter

Summary: Microsoft Scripting Guy, Ed Wilson, shows how to query multiple WMI classes with Windows PowerShell and return a single object.

Hey, Scripting Guy! Question Hey, Scripting Guy! I have this script that I have been working on for a while. It queries three different WMI classes. The first two classes are no problem because they only return a single item—for instance, information about the computer or the operating system. But the last class returns information from the disk drives. I have multiple disk drives; therefore, as my script is written now, I keep repeating the computer and the operating system information over and over. I know I am doing something wrong, but I am not sure what to do. Please help.

—FB

Hey, Scripting Guy! Answer Hello FB,

Microsoft Scripting Guy, Ed Wilson, is here. Today has been one of those days. You know the kind of day: an early morning meeting before breakfast, several meetings in the afternoon, and then another meeting after supper in the evening. Yep, a day’s worth of meetings always offers unique opportunities and challenges.

Between meetings, I check email that comes to scripter@microsoft.com. Personally, I do not check email during meetings because I consider it rude to the presenter. But maybe that is just me. If I attend a meeting, I feel that I should pay attention—or else I do not need to be in the meeting in the first place.

Hmm… something on the forums

FB, interestingly enough, there is a question similar to yours, but not exact, on the Official Scripting Guys Forum. Your problem is that you are trying to create a single object from within your script, yet you are returning multiple objects. In addition, your operating system information and your computer information is a single object, but you have multiple objects that represent your disk drives. This results in a ragged object. The way your script currently works, everything is inside the loop, and you return the same information multiple times. The key is to use Begin, Process, and End in your script.

Begin at the beginning

The Begin section of a script runs one time. This is a great place to put things that you want to use to initialize the script—or things that you do not need to process after you receive the information. In this script, I perform two WMI queries and create a hash table. The two WMI queries obtain computer and operating system information. The hash table is to be used to create a custom object at the end of the script. The Begin keyword accepts a script block (delimited by a pair of curly brackets).

Begin {

 [wmi]$os = Get-WmiObject -Class win32_operatingsystem

 [wmi]$cs = Get-WmiObject -Class win32_computersystem

 [hashtable]$osProperties = @{

    ‘OSVersion’=$os.version;

    ‘OSBuild’=$os.buildnumber;

    ‘SPVersion’=$os.servicepackmajorversion;

    ‘Model’=$cs.model;

    ‘Manufacturer’=$cs.manufacturer;

    ‘RAM’=$cs.totalphysicalmemory / 1GB -as [int];

    ‘Sockets’=$cs.numberofprocessors;

    ‘Cores’=$cs.numberoflogicalprocessors;

    ‘SystemType’=$cs.SystemType}}

Process stuff

The Process portion of the script runs one time for each object it must process. If there are no objects, the Process section does not run. In this portion of the script, the drives return an array of drive objects. The size, the freespace, and the percent of utilization become custom properties on the objects. This is the script that accomplishes this portion of the task:

Process {

[array]$disks = Get-WmiObject -Class win32_logicaldisk -filter ‘drivetype = 3’ |

  Select-Object -Property `

   @{L = ‘size’; E = {[math]::Round($_.size /1gb,2)} } ,

   @{L = ‘free’; E ={[math]::Round($_.freespace /1gb,2)}},

   @{L = ‘percent’; E = {[math]::Round(($_.freespace/$_.size)*100,2)}} }

The end

The End keyword, like the Begin keyword, specifies the section of the script that runs one time. This time, however, the section runs one time after the process section. The hash table created in the Begin section is now used to add the disk information to the object. Finally, a new PSCustomObject is created and the properties added. This is the script that accomplishes this task:

End {

  [hashtable]$osproperties.Add(‘disks’,$disks)

  New-Object -TypeName PSCustomObject -Property $osProperties } 

When the script runs, the following results appear:

Image of command output

FB, that is all there is to using multiple WMI classes in the same script. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

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

The "Scripting Guys" is a historical title passed from scripter to scripter. The current revision has morphed into our good friend Doctor Scripto who has been with us since the very beginning.

0 comments

Discussion are closed.