6.3. Get System Information from WMIWindows Management Instrumentation (WMI) is a technology for storing and working with system-management information. It contains representation of the full enterprise ecosystem, including hardware description, system information, and knowledge of application deployment. MSH makes WMI information available in the shell by means of the get-wmiobject cmdlet. Data within WMI is stored by class, which is a scheme that groups together similar categories of data. In this section, we'll focus on the Win32 classes , which contain the majority of information about a Windows system. 6.3.1. How Do I Do That?Let's begin by looking at the output of get-wmiobject for a few of the very general classes, such as the system processor and BIOS: MSH D:\MshScripts> get-wmiobject Win32_Processor AddressWidth : 32 Architecture : 0 Availability : 3 Caption : x86 Family 6 Model 13 Stepping 6 ConfigManagerErrorCode : ConfigManagerUserConfig : CpuStatus : 1 CreationClassName : Win32_Processor CurrentClockSpeed : 1395 CurrentVoltage : DataWidth : 32 Description : x86 Family 6 Model 13 Stepping 6 DeviceID : CPU0 ErrorCleared : ErrorDescription : ExtClock : 100 Family : 2 InstallDate : L2CacheSize : 0 L2CacheSpeed : LastErrorCode : Level : 6 LoadPercentage : 0 Manufacturer : GenuineIntel MaxClockSpeed : 1395 Name : Intel(R) Pentium(R) M processor 1.60GHz OtherFamilyDescription : PNPDeviceID : PowerManagementCapabilities : PowerManagementSupported : False ProcessorId : 07C0A93B000006D6 ProcessorType : 3 Revision : 3334 Role : CPU SocketDesignation : X1 Status : OK StatusInfo : 3 Stepping : 6 SystemCreationClassName : Win32_ComputerSystem SystemName : MONAD UniqueId : UpgradeMethod : 10 Version : Model 13, Stepping 6 VoltageCaps : 6 _ _GENUS : 2 _ _CLASS : Win32_Processor _ _SUPERCLASS : CIM_Processor _ _DYNASTY : CIM_ManagedSystemElement _ _RELPATH : Win32_Processor.Device _ _PROPERTY_COUNT : 44 _ _DERIVATION : {CIM_Processor, CIM_LogicalDevice, CIM_LogicalElement, CIM_ManagedSystemElement} _ _SERVER : MONAD _ _NAMESPACE : root\cimv2 _ _PATH : \\MONAD\root\cimv2:Win32_Processor.DeviceID ="CPU0" MSH D:\MshScripts> get-wmiobject Win32_BIOS SMBIOSBIOSVersion : 080002 Manufacturer : American Megatrends Inc. Name : BIOS Date: 08/14/03 19:41:02 Ver: 08.00.02 SerialNumber : 2265-1368-5332-4363-8258-5715-43 Version : A M I - 8000314 Although the list of information that comes back from the cmdlet can be quite long in cases, it's returned in the form of a structured object in the pipeline. As such, the standard formatting cmdlets can be used to simplify the output for reading and reporting: MSH D:\MshScripts> get-wmiobject Win32_Processor | format-list Name,Description,ProcessorID Name : Intel(R) Pentium(R) M processor 1.60GHz Description : x86 Family 6 Model 13 Stepping 6 ProcessorId : 07C0A93B000006D6 Some calls to get-wmiobject will result in several objects being created, one for each device (or component) of the class. For example, physical memory is comprised of a number of distinct memory modules that can easily be tabulated for review: MSH D:\MshScripts> get-wmiobject Win32_PhysicalMemory | format-table Tag,BankLabel,DeviceLocator,Capacity Tag BankLabel DeviceLocator Capacity --- --------- ------------- -------- Physical Memory 0 BANK0 DIMM1 268435456 Physical Memory 1 BANK1 DIMM2 268435456 Physical Memory 2 BANK1 DIMM2 268435456 Physical Memory 3 BANK1 DIMM2 268435456 As an enterprise class system for working with management information, WMI works seamlessly across machine boundaries. The get-wmiobject cmdlet will accept a -ComputerName option, which can be used to query the WMI store of another system in the local network. When combined with a small foreach loop, it becomes possible to audit a series of computers for their WMI information: MSH D:\MshScripts> $machines = @("hermes", "zeus", "apollo") MSH D:\MshScripts> $( >>foreach ($machine in $machines) >>{ >> get-wmiobject Win32_Processor -ComputerName $machine >>} >>) | format-table SystemName,Name >> SystemName Name ---------- ---- HERMES Intel(R) Pentium(R) M processor 1.60GHz ZEUS Intel(R) Pentium(R) 4 CPU 2.8GHz ZEUS Intel(R) Pentium(R) 4 CPU 2.8GHz APOLLO Intel(R) Pentium(R) 4 CPU 2.8GHz The fact that there are two rows in the table for the ZEUS machine is not a bugin fact, it's a sign that the script is working correctly. Because the ZEUS machine has two CPUs, the output of get-wmiobject is actually an array of two WMI objects, one for each processor. From here, it's a small step to include more information and build up a CSV file (with export-csv) that will prepare this data for handling inside a spreadsheet or other reporting system. 6.3.2. What Just Happened?The get-wmiobject is a great window into the operating system and into a machine's hardware. Although these examples focus on the hardware aspects of a system, WMI contains a far richer set of data. The available class names (such as Win32_BIOS) are predefined by the operating system. get-wmiobject can be called with a -list option to generate a list of all available classes in the current WMI namespace. (The default namespace is a good place to start exploring.) The default formatter understands many of the classes that come from the WMI cmdlet and, in some cases, displays only a few of the relevant properties. Don't be deceived, though, because there's often much more lurking inside. Take the Win32_OperatingSystem class, for example. By default, MSH shows six fields, including system directory, registered owner, and organization. However, pipe the output to format-list with a wildcard option (get-wmiobject Win32_OperatingSystem | format-list *), and the full set of the object's properties and methods is visible. In the last case, a foreach loop is used to build up the data from a range of machines. Because a foreach loop itself doesn't actually generate any output, we include it inside the evaluation syntax ($(...)). MSH understands that it must first evaluate the entire foreach loop (therefore querying each machine) and collect the objects generated by the loop before passing them downstream to the format-table cmdlet for output. 6.3.3. What About...Why do you need get-service when you can query the Win32_Service class? Everything seems to be available in WMI. For the two examples we saw earlier in this chapter, the specialized cmdlets exist to make a specific task easier to perform. The output of get-service (especially when combined with a command-line option) is immediately useful from within the shell and makes working with services a relatively simple task. From the shell, WMI is generally a read-only data store. Although there is no set-wmiobject cmdlet, it is possible to invoke WMI objects through the .NET Framework with InvokeMethod on the System.Management.ManagementObject class. Note that WMI methods are relatively uncommon and can require a lot of work (and caution) to use correctly. 6.3.4. Where Can I Learn More?The help page for get-wmiobject contains complete details about this cmdlet. In particular, there is support for WMI namespaces beyond the default root/cimv2 used here. There are also options to use different credentials when querying other machines for information. The WMI SDK documentation at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/operating_system_classes.asp has complete details of the class names that can be used in queries. |