In addition to working with namespaces, the inquisitive network administrator will want to explore the concept of classes. In WMI parlance, you have core classes, common classes, and dynamic classes. Core classes represent managed objects that apply to all areas of management. These classes provide a basic vocabulary for analyzing and describing managed systems. Two examples of core classes are parameters and the SystemSecurity class. Common classes are extensions to the core classes and represent managed objects that apply to specific management areas. However, common classes are independent from a particular implementation or technology. The CIM_UnitaryComputerSystem is an example of a common class. Core and common classes are not used as much by network administrators because they serve as templates from which other classes are derived.
Many of the classes stored in Root\cimv2, therefore, are abstract classes and are used as templates. However, a few classes in Root\cimv2 are dynamic classes used to hold actual information. The important aspect to remember about dynamic classes is that instances of a dynamic class are generated by a provider and are therefore more likely to retrieve “live” data from the system.
To produce a simple listing of WMI classes, you can use the Get-WmiObject cmdlet and specify the list argument. This code is shown here:
Get-WmiObject –list
A partial output from the previous command is shown here:
Win32_TSGeneralSetting Win32_TSPermissionsSetting Win32_TSClientSetting Win32_TSEnvironmentSetting Win32_TSNetworkAdapterListSetting Win32_TSLogonSetting Win32_TSSessionSetting Win32_DisplayConfiguration Win32_COMSetting Win32_ClassicCOMClassSetting Win32_DCOMApplicationSetting Win32_MSIResource Win32_ServiceControl Win32_Property
The following script, ListAllClassesInNameSpace.ps1, returns a list of classes found in the Root\cimv2 namespace. There are more than 900 classes listed in the Root\cimv2 namespace of most computers. The difference between the Get-WmiObject -list command and the ListAllClassesInNameSpace.ps1 script, besides length, is flexibility. With the Get-WmiObject -list command, you are pretty much limited to retrieving the name of the WMI classes. In the ListAllClassesInNameSpace.ps1 script, you are working directly with the WMI application programming interface (API), and as a result, you have complete flexibility in what information you retrieve and how you present it.
In the ListAllClassesInNameSpace.ps1, the script begins by assigning the shortcut value of dot (.) to the variable $strComputer. When used with WMI, the dot in the connection string means to run the command on the local machine. The $wmiNS variable holds the value of \Root\cimv2, which is the default WMI namespace in all modern Windows operating systems. The next seven variables are common to all scripts that use the WbemScripting.SWbemLocator method. The variables are listed in Table 5-1.
Variable Name | Variable Use |
---|---|
$strComputer | Name of computer to run the script on |
$wmiNS | WMI namespace containing WMI class used in the script |
$strUsr | User name for connection to remote computer |
$strPWD | Password of user connecting to remote machine |
$strLocl | Language to be used with WMI connection |
$strAuth | Credential authority, for example, Kerberos, NTLM |
$iFlag | Security flag; used to specify timeout value |
After declaring the seven common variables used in all WbemScripting.SWbemLocator scripts, we use the variable $objLocator to hold the WbemScripting.SWbemLocator object that is returned by the New-Object cmdlet. The New-Object command is shown here:
$objLocator = New-Object -comobject "WbemScripting.SWbemLocator"
The WbemScripting.SWbemLocator object only exposes a single method-the connectServer method. But this method can receive up to seven different arguments.
Because the connectServer method is so heavily parameterized, I decided to define a variable for each parameter. This ensures that parameters that are left out are placed in the correct order-as opposed to just padding a bunch of empty commas. The connectServer method call is shown here:
$objWMIService = $objLocator.ConnectServer($strComputer, $wmiNS, $strUsr, $strPWD, $strLocl, $strAuth, $iFLag)
The connectServer method returns an ISwbemServices object, which is held in the $objWMIService variable. The ISwbemServices object exposes a method called subClassesOf. The subClassesOf method returns a collection of WMI classes that is called an ISWbemObjectSet. The subClassesOf method call is shown here:
$colItems = $objWMIService.subClassesOf()
Each WMI class that gets returned is an ISwbemObject, which is adorned with many properties and methods. Each ISwbemObject is contained in the $objItem variable. The $colItems variable contains a collection. To retrieve the individual properties of the ISwbemObject, we need to have a way to pull a single object from the collection. To do this, we will use the ForEach-Object cmdlet. The ForEach-Object statement is seen here. Note that to save a little bit of typing, I decided to use the alias foreach.
foreach ($objItem In $colItems) { $objItem.path_.class }
Each individual object from the collection of objects is called $objItem. The ISwbemObject contained in the $objItem variable has a property called path_. When we query the path_ property, an ISWbemObjectPath object is returned. The ISWbemObjectPath object has a property called class. To get the name of each class contained in the Root\cimv2 namespace, we simply print out the value of the class property. The line of code that does this is shown here:
$objItem.path_.class
The completed ListAllClassesInNameSpace.ps1 script is shown here:
ListAllClassesInNameSpace.ps1
$strComputer = "." $wmiNS = "\root\cimv2" $strUsr ="" #Blank for current security. Domain\Username $strPWD = "" #Blank for current security. $strLocl = "MS_409" #US English. Can leave blank for current language $strAuth = "" #if specify domain in strUsr this must be blank $iFlag = "0" #only two values allowed: 0 and 128. $objLocator = New-Object -comobject "WbemScripting.SWbemLocator" $objWMIService = $objLocator.ConnectServer($strComputer, $wmiNS, $strUsr, $strPWD, $strLocl, $strAuth, $iFLag) $colItems = $objWMIService.subClassesOf() Write-Host "There are: " $colItems.count " classes in $wmiNS" foreach ($objItem In $colItems) { $objItem.path_.class }
Open the ListAllClassesNameSpaces.ps1 script in Notepad.exe or some other script editor and save it as yourname ExploringWmiObjects.ps1. The ExploringWmiObjects.ps1 script can be found in the scripts folder for this chapter.
Your script right now should look like the following:
$strComputer = "." $wmiNS = "\root\cimv2" $strUsr ="" #Blank for current security. Domain\Username $strPWD = "" #Blank for current security. $strLocl = "MS_409" #US English. Can leave blank for current language $strAuth = "" #if specify domain in strUsr this must be blank $iFlag = "0" #only two values allowed: 0 and 128. $objLocator = New-Object -comobject "WbemScripting.SWbemLocator" $objWMIService = $objLocator.ConnectServer($strComputer, ` $wmiNS, $strUsr, $strPWD, $strLocl, $strAuth, $iFLag) $colItems = $objWMIService.subClassesOf() Write-Host "There are: " $colItems.count " classes in $wmiNS" foreach ($objItem In $colItems) { $objItem.path_.class }
Run the script, but after a second, press Ctrl-c to halt execution of the script. You will see an output similar to the following:
There are: 1000 classes in \root\cimv2 __SystemClass __thisNAMESPACE __Provider __Win32Provider __IndicationRelated __EventGenerator __TimerInstruction __IntervalTimerInstruction __AbsoluteTimerInstruction __Event __NamespaceOperationEvent __NamespaceDeletionEvent __NamespaceCreationEvent __NamespaceModificationEvent __InstanceOperationEvent __MethodInvocationEvent __InstanceCreationEvent __InstanceModificationEvent
Comment out everything below the New-Object line statement in your script. The revised script is shown here:
$strComputer = "." $wmiNS = "\root\cimv2" $strUsr ="" #Blank for current security. Domain\Username $strPWD = "" #Blank for current security. $strLocl = "MS_409" #US English. Can leave blank for current language $strAuth = "" #if specify domain in strUsr this must be blank $iFlag = "0" #only two values allowed: 0 and 128. $objLocator = New-Object -comobject "WbemScripting.SWbemLocator" # $objWMIService = $objLocator.ConnectServer($strComputer, ` # $wmiNS, $strUsr, $strPWD, $strLocl, $strAuth, $iFLag) # # $colItems = $objWMIService.subClassesOf() # Write-Host "There are: " $colItems.count " classes in $wmiNS" # foreach ($objItem In $colItems) # { # $objItem.path_.class # }
Save and run the script. You should not see any output, nor should you see any errors.
On the line below the New-Object line in your script (where the first line of commented code resides), add a line that pipelines the object contained in the $objLocator variable to the Get-Member cmdlet. This code is shown here:
$objLocator | Get-Member
The results from the previous command are shown here:
TypeName: System.__ComObject#{} Name MemberType Definition ---- ---------- ---------- ConnectServer Method ISWbemServices ConnectServer (string, string, strin... Security_ Property ISWbemSecurity Security_ () {get}
Remove the comments from the connectServer method call. These two lines of code are shown here:
$objWMIService = $objLocator.ConnectServer($strComputer, ` $wmiNS, $strUsr, $strPWD, $strLocl, $strAuth, $iFLag)
Save and run the script. You should see exactly the same results you saw the previous time.
Pipeline the object contained in the $objWMIService variable to the Get-Member cmdlet. The code to do this is shown here:
$objWMIService | Get-Member
Save and run the script. The results from this command are shown here:
TypeName: System.__ComObject#{} Name MemberType Definition ---- ---------- ---------- ConnectServer Method ISWbemServices ConnectServer (string, string, strin... Security_ Property ISWbemSecurity Security_ () {get} TypeName: System.__ComObject#{} Name MemberType Definition ---- ---------- ---------- AssociatorsOf Method ISWbemObjectSet AssociatorsOf (string,... AssociatorsOfAsync Method void AssociatorsOfAsync (IDispatch, st... Delete Method void Delete (string, int, IDispatch) DeleteAsync Method void DeleteAsync (IDispatch, string, i... ExecMethod Method ISWbemObject ExecMethod (string, strin... ExecMethodAsync Method void ExecMethodAsync (IDispatch, strin... ExecNotificationQuery Method ISWbemEventSource ExecNotificationQuer... ExecNotificationQueryAsync Method void ExecNotificationQueryAsync (IDisp... ExecQuery Method ISWbemObjectSet ExecQuery (string, str... ExecQueryAsync Method void ExecQueryAsync (IDispatch, string... Get Method ISWbemObject Get (string, int, IDispatch) GetAsync Method void GetAsync (IDispatch, string, int,... InstancesOf Method ISWbemObjectSet InstancesOf (string, i... InstancesOfAsync Method void InstancesOfAsync (IDispatch, stri... Put Method ISWbemObjectPath Put (ISWbemObjectEx, ... PutAsync Method void PutAsync (ISWbemSink, ISWbemObjec... ReferencesTo Method ISWbemObjectSet ReferencesTo (string, ... ReferencesToAsync Method void ReferencesToAsync (IDispatch, str... SubclassesOf Method ISWbemObjectSet SubclassesOf (string, ... SubclassesOfAsync Method void SubclassesOfAsync (IDispatch, str... Security_ Property ISWbemSecurity Security_ () {get}
Remove the comment character from the line that calls the subClassesOf() method. On the next line following that line of code, pipeline the object contained in the $colItems variable to the Get-Member cmdlet. These two lines of code are shown here:
$colItems = $objWMIService.subClassesOf() $colItems | Get-Member
Save and run the script. The resulting output is shown here:
TypeName: System.__ComObject#{} Name MemberType Definition ---- ---------- ---------- ConnectServer Method ISWbemServices ConnectServer (string, string, strin... Security_ Property ISWbemSecurity Security_ () {get} TypeName: System.__ComObject#{} Name MemberType Definition ---- ---------- ---------- AssociatorsOf Method ISWbemObjectSet AssociatorsOf (string,... AssociatorsOfAsync Method void AssociatorsOfAsync (IDispatch, st... Delete Method void Delete (string, int, IDispatch) DeleteAsync Method void DeleteAsync (IDispatch, string, i... ExecMethod Method ISWbemObject ExecMethod (string, strin... ExecMethodAsync Method void ExecMethodAsync (IDispatch, strin... ExecNotificationQuery Method ISWbemEventSource ExecNotificationQuer... ExecNotificationQueryAsync Method void ExecNotificationQueryAsync (IDisp... ExecQuery Method ISWbemObjectSet ExecQuery (string, str... ExecQueryAsync Method void ExecQueryAsync (IDispatch, string... Get Method ISWbemObject Get (string, int, IDispatch) GetAsync Method void GetAsync (IDispatch, string, int,... InstancesOf Method ISWbemObjectSet InstancesOf (string, i... InstancesOfAsync Method void InstancesOfAsync (IDispatch, stri... Put Method ISWbemObjectPath Put (ISWbemObjectEx, ... PutAsync Method void PutAsync (ISWbemSink, ISWbemObjec... ReferencesTo Method ISWbemObjectSet ReferencesTo (string, ... ReferencesToAsync Method void ReferencesToAsync (IDispatch, str... SubclassesOf Method ISWbemObjectSet SubclassesOf (string, ... SubclassesOfAsync Method void SubclassesOfAsync (IDispatch, str... Security_ Property ISWbemSecurity Security_ () {get} TypeName: System.__ComObject#{} Name MemberType Definition ---- ---------- ---------- AssociatorsAsync_ Method void AssociatorsAsync_ (IDispatch, string, str... Associators_ Method ISWbemObjectSet Associators_ (string, string, ... Clone_ Method ISWbemObject Clone_ () CompareTo_ Method bool CompareTo_ (IDispatch, int) DeleteAsync_ Method void DeleteAsync_ (IDispatch, int, IDispatch, ... Delete_ Method void Delete_ (int, IDispatch) ExecMethodAsync_ Method void ExecMethodAsync_ (IDispatch, string, IDis... ExecMethod_ Method ISWbemObject ExecMethod_ (string, IDispatch, i... GetObjectText_ Method string GetObjectText_ (int) GetText_ Method string GetText_ (WbemObjectTextFormatEnum, int... InstancesAsync_ Method void InstancesAsync_ (IDispatch, int, IDispatc... Instances_ Method ISWbemObjectSet Instances_ (int, IDispatch) PutAsync_ Method void PutAsync_ (IDispatch, int, IDispatch, IDi... Put_ Method ISWbemObjectPath Put_ (int, IDispatch) ReferencesAsync_ Method void ReferencesAsync_ (IDispatch, string, stri... References_ Method ISWbemObjectSet References_ (string, string, b... Refresh_ Method void Refresh_ (int, IDispatch) SetFromText_ Method void SetFromText_ (string, WbemObjectTextForma... SpawnDerivedClass_ Method ISWbemObject SpawnDerivedClass_ (int) SpawnInstance_ Method ISWbemObject SpawnInstance_ (int) SubclassesAsync_ Method void SubclassesAsync_ (IDispatch, int, IDispat... Subclasses_ Method ISWbemObjectSet Subclasses_ (int, IDispatch) Derivation_ Property Variant Derivation_ () {get} Methods_ Property ISWbemMethodSet Methods_ () {get} Path_ Property ISWbemObjectPath Path_ () {get} Properties_ Property ISWbemPropertySet Properties_ () {get} Qualifiers_ Property ISWbemQualifierSet Qualifiers_ () {get} Security_ Property ISWbemSecurity Security_ () {get} SystemProperties_ Property ISWbemPropertySet SystemProperties_ () {get}
If we were to use the Get-Member cmdlet to discover the members of object contained in the $objItem variable, we would see the list printed out 1,000 times because the $colItems variable contains 1,000 instances of classes on my machine. To avoid this situation, we will use a different method than the subClassesOf() method. Save your script with a new name. Call your new script yourname GetWmiObject.ps1.
Under the $wmiNS variable, create a new variable. Call the variable $wmiClass and assign the string WIN32_Service to it. This line of code is shown here:
$wmiClass = "WIN32_Service"
To limit the output of the Get-Member cmdlets to only the members of the WIN32_Service class, comment out the two Get-Member lines of code that print out the members of $objLocator and $objWmiService. This section of code is shown here:
$objLocator = New-Object -comobject "WbemScripting.SWbemLocator" #$objLocator | Get-Member $objWMIService = $objLocator.ConnectServer($strComputer, $wmiNS, $strUsr, $strPWD, $strLocl, $strAuth, $iFLag) #$objWMIService | Get-Member
Rename the $colItems variable to $objItem because the variable will be used to hold only a single object. Change the Subclasses() method to the Get method. Have the Get method retrieve the WMI class contained in the $wmiClass variable. This revised line of code is shown here:
$objItem = $objWMIService.Get($wmiClass)
Pipeline the $objItem object to the Get-Member cmdlet. This line of code is shown here:
$objItem | Get-Member
Save and run your script. The output will look like the following:
TypeName: System.__ComObject#{} Name MemberType Definition ---- ---------- ---------- AssociatorsAsync_ Method void AssociatorsAsync_ (IDispatch, string, str... Associators_ Method ISWbemObjectSet Associators_ (string, string, ... Clone_ Method ISWbemObject Clone_ () CompareTo_ Method bool CompareTo_ (IDispatch, int) DeleteAsync_ Method void DeleteAsync_ (IDispatch, int, IDispatch, ... Delete_ Method void Delete_ (int, IDispatch) ExecMethodAsync_ Method void ExecMethodAsync_ (IDispatch, string, IDis... ExecMethod_ Method ISWbemObject ExecMethod_ (string, IDispatch, i... GetObjectText_ Method string GetObjectText_ (int) GetText_ Method string GetText_ (WbemObjectTextFormatEnum, int... InstancesAsync_ Method void InstancesAsync_ (IDispatch, int, IDispatc... Instances_ Method ISWbemObjectSet Instances_ (int, IDispatch) PutAsync_ Method void PutAsync_ (IDispatch, int, IDispatch, IDi... Put_ Method ISWbemObjectPath Put_ (int, IDispatch) ReferencesAsync_ Method void ReferencesAsync_ (IDispatch, string, stri... References_ Method ISWbemObjectSet References_ (string, string, b... Refresh_ Method void Refresh_ (int, IDispatch) SetFromText_ Method void SetFromText_ (string, WbemObjectTextForma... SpawnDerivedClass_ Method ISWbemObject SpawnDerivedClass_ (int) SpawnInstance_ Method ISWbemObject SpawnInstance_ (int) SubclassesAsync_ Method void SubclassesAsync_ (IDispatch, int, IDispat... Subclasses_ Method ISWbemObjectSet Subclasses_ (int, IDispatch) Derivation_ Property Variant Derivation_ () {get} Methods_ Property ISWbemMethodSet Methods_ () {get} Path_ Property ISWbemObjectPath Path_ () {get} Properties_ Property ISWbemPropertySet Properties_ () {get} Qualifiers_ Property ISWbemQualifierSet Qualifiers_ () {get} Security_ Property ISWbemSecurity Security_ () {get} SystemProperties_ Property ISWbemPropertySet SystemProperties_ () {get}
If your results are not similar to the output shown, compare your script with the GetWmiObject.ps1 script.