Summary: Use Windows PowerShell to check for WMI dependencies on Windows 7 and Windows Server 2008 R2.

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I am very excited about using the WMI reliability classes for monitoring purposes. As you mentioned in your previous articles, it is not automatically enabled on Windows Server 2008 R2. This means that it will cause my script to fail if the class is not present. Is there some way to check to see if the WMI reliability provider exists? I imagine I could use try/catch/finally, but that seems like cheating. I would like to know exactly how to check to see if the provider exists.

-- SK

 

Hey, Scripting Guy! Answer

Hello SK,

Microsoft Scripting Guy Ed Wilson here. Windows PowerShell is a cool product. For me, it is the best of both worlds: a tool that is useful, and a tool that is fun to use. There are plenty of tools out there that are useful, but that are not very fun to use; a 20-pound sledgehammer is one such example. Because Windows PowerShell is so fun, it has inspired “rock videos” such as Highway to PowerShell by Windows PowerShell MVP Sean Kearney.

SK, to ensure that the ReliabilityMetricsProvider exists on a local or remote computer, you can query for the __Provider WMI system class and look for a provider with the name of ReliabilityMetricsProvider. This is shown here:

PS C:\> Get-WmiObject -Class __provider -filter "name = 'ReliabilityMetricsProvider'"
 
-computername hyperv-box
__GENUS : 2
__CLASS : __Win32Provider
__SUPERCLASS : __Provider
__DYNASTY : __SystemClass
__RELPATH : __Win32Provider.Name="ReliabilityMetricsProvider"
__PROPERTY_COUNT : 24
__DERIVATION : {__Provider, __SystemClass}
__SERVER : EX1
__NAMESPACE : ROOT\cimv2
__PATH : \\EX1\ROOT\cimv2:__Win32Provider.Name="ReliabilityMe
tricsProvider"
ClientLoadableCLSID :
CLSID : {D7C3453E-1F1C-48CD-AFE6-CFF2A937D337}
Concurrency :
DefaultMachineName :
Enabled :
HostingModel : NetworkServiceHost:[ReliabilityMetricsProvider]
ImpersonationLevel : 0
InitializationReentrancy : 0
InitializationTimeoutInterval :
InitializeAsAdminFirst :
Name : ReliabilityMetricsProvider
OperationTimeoutInterval :
PerLocaleInitialization : False
PerUserInitialization : False
Pure : True
SecurityDescriptor :
SupportsExplicitShutdown :
SupportsExtendedStatus :
SupportsQuotas :
SupportsSendStatus :
SupportsShutdown :
SupportsThrottling :
UnloadTimeout :
Version :


PS C:\>

As you can see from the above output, the reliability provider is installed on the remote computer named hyperv-box. If I query the Win32_ReliabilityRecords class on the hyperv-box computer, the following is output if Group Policy has not enabled the reliabilityMetricsProvider. Notice that the error message is “not available.” This lets me know the class exists, but it is not available for use at this time. Using Group Policy to enable the reliabilityMetricsProvider was discussed in yesterday’s Hey, Scripting Guy! Blog post.

PS C:\> Get-WmiObject -Class win32_reliabilityrecords -CN hyperv-box
Get-WmiObject : Not available
At line:1 char:14
+ Get-WmiObject <<<< -Class win32_reliabilityrecords -CN hyperv-box
   
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], ManagementException
   
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

PS C:\>

When I query the remote computer named dc1, as seen here, nothing is returned because that machine is running Windows Server 2008—but not the R2 edition:

PS C:\> Get-WmiObject -Class __provider -filter "name = 'ReliabilityMetricsProvider'"
 
-computername dc1
PS C:\>

If I query the win32_reliabilityrecords WMI class on dc1, the error that is returned says invalid class. This lets me know the class does not exist:

PS C:\> Get-WmiObject -Class win32_reliabilityrecords -CN dc1
Get-WmiObject : Invalid class
At line:1 char:14
+ Get-WmiObject <<<< -Class win32_reliabilityrecords -CN dc1
   
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], ManagementException
   
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

PS C:\>

Therefore, there are several potential scenarios: the provider does not exist, the provider does exist but is not enabled, or the provider exists and is enabled.

Testing for the presence of the Windows Installer WMI provider (msiprov) was covered in detail in a series of two Hey, Scripting Guy! Blog posts from last year. That information is useful in understanding WMI providers and applies to more than just the Windows Installer provider.

Querying for the provider reveals if the provider exists, but does not reveal if the provider is enabled on a Windows Server 2008 R2 machine. To do that requires finding out if the Group Policy has enabled the Configure Reliability WMI Providers policy setting. The Group Policy spreadsheet for Windows Server 2008 R2 and Windows 7 provides the registry setting to detect if the Configure Reliability WMI Providers policy setting has been enabled. The Group Policy spreadsheet is shown in the following image.

Image of Group Policy spreadsheet

Armed with the proper registry key, which exists only if the Group Policy setting has been enabled, the registry key can be detected using Windows PowerShell scripting. When the Configure Reliability WMI Providers policy setting is enabled, the registry key will be set to 1. This is shown in the following image.

Image of registry key set to 1 when policy setting is enabled

If the Configure Reliability WMI Providers Group policy setting is set to disable, the value stored in the WMIEnable registry key will be 0; therefore, 1 means the provider is specifically enabled, and 0 means it is specifically disabled. If the registry key is missing, the operating system defaults will be in effect; Windows 7 will have the provider enabled, and Windows Server 2008 R2 will have the provider disabled.

The Test-ReliablityProvider.ps1 script contains a function that returns true if the provider is enabled, and false if the provider is either missing or disabled. The complete Test-ReliabilityProvider.ps1 script is shown here.

Test-ReliabilityProvider.ps1

Function Test-ReliabilityProvider

{ 
 
<#
  
.Synopsis
   
This function checks for the presence of the WMI Reliability provider
  
.Description
   
This function checks for the presence of the WMI Reliability provider
  
.Example
   
Test-ReliabilityProvider
   
Returns true if reliability exists and is enabled on local computer. 
  
.Example
   
Test-ReliabilityProvider -computer berlin
   
Tests for presence of reliability provider on remote computer named berlin.
   
Returns true if exists and is enabled, false otherwise 
  
.Parameter Computer
   
Name of remote computer to test
  
.Inputs
   
[string]
  
.Outputs
   
[boolean]
  
.Notes
   
NAME: Test-ReliabilityProvider
   
AUTHOR: ed wilson, msft
   
LASTEDIT: 09/27/2010 13:59:47
   
KEYWORDS: Operating System, Registry, Scripting Techniques, WMI
   
HSG: HSG-10-06-10
  
.Link
   
Http://www.ScriptingGuys.com
 
#Requires -Version 2.0
 
#>
 
[cmdletBinding()]
 
Param ([string]$computer = ".")
 
$provider = Get-WmiObject -Class __provider -filter `
"name = 'ReliabilityMetricsProvider'"
-computername $computer
 
If($provider -ne $null)
  
{
   
Write-Verbose "Reliability Provider found"
   
$hklm = 2147483650
   
$key = "SOFTWARE\Policies\Microsoft\Windows\Reliability Analysis\WMI"
   
$value = "WmiEnable"
   
$wmi = [wmiclass]"\\$computer\root\default:stdRegProv"
   
if( ($wmi.GetDWORDValue($hklm,$key,$value)).uValue -eq 1) 
    
{
     
Write-Verbose "Reliability Provider enabled via Group Policy" 
     
Return $true 
     
}
   
Else 
    
{
      
Write-verbose "Reliability Provider not enabled via Group Policy"
      
Return $false 
     
}
  
}
 
Else 
 
{
  
Write-verbose "Reliability Provider does not exist" 
   
Return $false 
  
}
} # end function Test-ReliabilityProvider 
 
# *** Entry Point to script ***


#Test-ReliabilityProvider -computer "."

The first thing that is done in the script is to add comment-based help. This is shown here:

Function Test-ReliabilityProvider
{ 
 
<#
  
.Synopsis
   
This function checks for the presence of the WMI Reliability provider
  
.Description
   
This function checks for the presence of the WMI Reliability provider
  
.Example
   
Test-ReliabilityProvider
   
Returns true if reliability exists and is enabled on local computer. 
  
.Example
   
Test-ReliabilityProvider -computer berlin
   
Tests for presence of reliability provider on remote computer named berlin.
   
Returns true if exists and is enabled, false otherwise 
  
.Parameter Computer
   
Name of remote computer to test
  
.Inputs
   
[string]
  
.Outputs
   
[boolean]
  
.Notes
   
NAME: Test-ReliabilityProvider
   
AUTHOR: ed wilson, msft
   
LASTEDIT: 09/27/2010 13:59:47
   
KEYWORDS: Operating System, Registry, Scripting Techniques, WMI
   
HSG: HSG-10-06-10
  
.Link
    
Http://www.ScriptingGuys.com
 
#Requires -Version 2.0
 
#>

Comment-based help has been discussed in several Hey, Scripting Guy! Blog posts. In the series of Hey, Scripting Guy! Blog posts about customizing the Windows PowerShell ISE, I even developed a function that will automatically add comment-based help to the Windows PowerShell script. The nice thing about using comment-based help is that it allows you to use the Get-Help cmdlet to retrieve nicely formatted help information from the function. This is shown in the following image.

Image of using formatted help information from function

The script then uses the [cmdletBinding()] directive. When the [cmdletBinding()] directive is used, the function will automatically use the standard parameters. For example, the –verbose standard parameter would normally need to be specifically enabled. But when [cmdletBinding()] is used, all that is required is to use the Write-Verbose command in the appropriate portion of the script. When the function is called with the –verbose parameter, the content supplied by the Write-Verbose cmdlet will be displayed. This is shown in the following image.

Image of content supplied by Write-Verbose cmdlet when function is called with -verbose parameter

The existence of the ReliabilityMetricsProvider is determined by querying the __Provider WMI class:

 $provider = Get-WmiObject -Class __provider -filter `
"name = 'ReliabilityMetricsProvider'"
-computername $computer

If the provider exists, the stdregprov WMI class is used to determine if Group Policy has enabled the provider. The reason for using the stdregprov WMI class is that WMI was already being used to query for the existence of the WMI provider. If this had not been the case, I would have used the Windows PowerShell HKLM PowerShell drive. The use of the stdregprov WMI class has been discussed several times on the Hey, Scripting Guy! Blog. The code that queries the registry is shown here:

If($provider -ne $null)
  
{
   
Write-Verbose "Reliability Provider found"
   
$hklm = 2147483650
   
$key = "SOFTWARE\Policies\Microsoft\Windows\Reliability Analysis\WMI"
   
$value = "WmiEnable"
   
$wmi = [wmiclass]"\\$computer\root\default:stdRegProv"
   
if( ($wmi.GetDWORDValue($hklm,$key,$value)).uValue -eq 1) 
    
{
     
Write-Verbose "Reliability Provider enabled via Group Policy" 
     
Return $true 
     
}

The script returns the Boolean value $false to the calling code if the WMI provider does not exist, or if the WMI provider is not enabled via Group Policy. This is shown here:

    Else 
    
{
      
Write-verbose "Reliability Provider not enabled via Group Policy"
      
Return $false 
     
}
  
}
 
Else 
 
{
  
Write-verbose "Reliability Provider does not exist" 
   
Return $false 
  
}

SK, that is all there is to using Windows PowerShell to check for the status of the WMI Reliability provider. Performance Week will continue tomorrow when we will complete talking about checking for the Reliability provider.

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

 

Ed Wilson and Craig Liebendorfer, Scripting Guys