IsManageable

One issue that always seems to come up when using WMI to manage remote machines is being able to communicate with WMI on the remote machine. This is especially an issue when the remote server sits behind a firewall or across a WAN. I got tired of running complex WMI queries only to have them fail because the computer is unavailable.  I need a way to validate the computer before carrying out the main part of any script or automation task.

Pinging the computer is not a valid test as sometimes network devices are configured to block that traffic. Or, just because a computer does respond to a ping, doesn’t mean I can use WMI.  Ping uses ICMP and WMI uses RPC.  Totally different protocols. 

What I came up with is a PowerShell function I call IsManageable.  I know it probably doesn’t fit the Powershell naming convention so feel free to rename it.  But it makes sense to me. The function will return True if it can establish a WMI connection or False if it can’t.

Function IsManageable {
param([string]$Computer,`
[System.Management.Automation.PSCredential]$credential)

if ($credential -IS [System.Management.Automation.PSCredential])
{
#use alternate credentials if supplied
$sb={(Get-WmiObject win32_operatingsystem -computer $Computer `
-credential $credential -erroraction SilentlyContinue).caption}
}
else {
#use existing credentials
$sb={(Get-WmiObject win32_operatingsystem -computer $Computer `
-erroraction SilentlyContinue).caption}
}

if (&$sb -IS [STRING])
{
Return $TRUE
}
else
{
Return $FALSE
}
} #end function

The function takes a computername as a run time parameter, as well as a PSCredential object. The credential is an optional parameter. The preferred method is to specify an alternate credential before using this function like this:

$cred=Get-Credential(“domain\administrator”)

Then run

PS C:\> IsManageable DC01 $cred

You could also use this expression which will prompt you for alternate credentials:

PS C:\> IsManageable DC01 (get-credential)

The function checks the second parameter and if it is a PSCredential, then it creates a Get-WMIObject script block that uses -credential:

if ($credential -IS [System.Management.Automation.PSCredential])
{
#use alternate credentials if supplied
$sb={(Get-WmiObject win32_operatingsystem -computer $Computer `
-credential $credential -erroraction SilentlyContinue).caption}
}

Otherwise, the script block is created without it:

else {
#use existing credentials
$sb={(Get-WmiObject win32_operatingsystem -computer $Computer `
-erroraction SilentlyContinue).caption}
}

The last part of the function checks the value of the script block and if it is a [String} type,

if (&$sb -IS [STRING])

then I know a value was returned for the operating system caption and thus the computer is manageable via WMI. By using a script block, it makes my function a little easier to read.

You’ll also notice that I’ve set the -erroraction parameter for the Get-Wmiobject cmdlet to SilentlyContinue. This is because I want to cmdlet to finish, even if an error is raised. I’m assuming that if an error is raised, that the computer is not manageable and the function will return False. You will still get an error if you try to access a machine without the proper credentials, which I suppose tells you the computer is manageable, provided you use alternate credentials.

Even if you don’t need this function, I hope it serves as a useful demonstration of the -IS operator and how to use scriptblocks.