rpr
rpr

Reputation: 121

Is there any Faster method to do WMI query from Powershell ..?

Wrote a small script to find the number Multipaths from the windows servers using WMI query. It works well for the servers which can connect directly without any issue. But if one server is pingable but not able to reach through WMI script, it takes long time to return the error ( for example if a linux server hostname is present in the servers.txt list).. Can somebody help me to do the same in a faster way..?

$Servers = Get-Content .\Servers.txt

$ErrorActionPreference = ‘SilentlyContinue’

FOREACH ($Server in $Servers) {

Write-Host $Server -nonewline

if (test-connection -computername $Server -Count 1 -quiet) {

$Name = $null
$NoPath =$null
$MPIODisks =$null

$MPIODisks = Get-WmiObject -Namespace root\wmi -Class mpio_disk_info -ComputerName "$Server" |Select-Object "DriveInfo"

    if ($MPIODisks -eq $Null) {

    write-host "`t - Unable to connect" -fore "RED"

    } else {    

        write-host ""
        write-host "Drive Name `tNo.Path" -fore "yellow"

            Foreach ($Disk in $MPIODisks) {
                $mpiodrives = $disk.DriveInfo

                    foreach ($Drive in $mpiodrives) {
                $Name = $Drive.Name
                $NoPath = $Drive.Numberpaths

                    If ($NoPath -lt 4) {
                    Write-Host $Name `t -nonewline
                    write-host $NoPath -fore "Red"
                    } else {
                    Write-Host $Name `t -nonewline
                    write-host $NoPath -fore "Green"
                    }
                    }
            }

    }

    write-host ""

} else {

write-host "`t- Unknown Host" -fore "Red"
write-host ""
}

}

Upvotes: 0

Views: 3260

Answers (2)

Joachim Isaksson
Joachim Isaksson

Reputation: 181097

As an alternative, you could ask all servers for the result at once by passing them all into the query and avoiding the slow loop querying one server at a time. I don't have any MPIO drives to test with, but it could look something like this (using Get-Ciminstance which takes a timeout parameter):

$servers = Get-Content .\Servers.txt

# Get data from all servers with timeout
$servers_ok = Get-CimInstance -computername $servers -Namespace root\wmi -Class mpio_disk_info -ErrorAction SilentlyContinue -OperationTimeoutSec 1 | group pscomputername

# Output which servers gave no result back
foreach($no_result in $($servers | where { $_ -NotIn $servers_ok.Name })) {
    write-host "No result for $no_result" -ForegroundColor Red
}

# Loop over the results and output
foreach($server in $servers_ok) {

    Write-Host $server.Name 

    foreach($mpiodisk in $server.group)  {

        $mpiodrives = $mpiodisk.DriveInfo

        foreach ($mpiodrive in $mpiodrives) {

            $name = $mpiodrive.Name
            $noPath = $mpiodrive.NumberPaths

            If ($NoPath -lt 4) {
                write-host $name `t -nonewline
                write-host $noPath -fore "Red"
            } else {
                write-host $name `t -nonewline
                write-host $noPath -fore "Green"
            }
        }
    }
}

Upvotes: 2

user847990
user847990

Reputation:

There is a connect item for Get-WmiObject to add a timeout parameter. A workaround noted in that item is to just pipe your WMI command to Wait-Job and specify a timeout period in seconds.

As long as your on PS version 3.0 or higher, this should work for you:

Get-WmiObject win32_computersystem -ComputerName <hostname> -AsJob | Wait-Job -Timeout 10 | Receive-Job

Upvotes: 4

Related Questions