超时Get-WMIObject cmdlet

时间:2012-03-14 21:25:26

标签: powershell wmi

我运行一个执行许多WMI查询的脚本 - 但如果服务器没有回答,则cmdlet会挂起。 有没有什么方法可以让这个(或任何其他cmndlet)超时并在X秒过去时退出?

修改

感谢来自mjolinor的提示,解决方案是将其作为-asjob运行并在while循环中设置超时。但是这已经从一个工作中运行(从Start-Job开始)。那么我怎么知道我正在控制正确的工作呢?

这是我已经开始的工作中的代码:

Get-WmiObject Win32_Service -ComputerName $server -AsJob

$Complete = Get-date

While (Get-Job -State Running){
    If ($(New-TimeSpan $Complete $(Get-Date)).totalseconds -ge 5) {
        echo "five seconds has passed, removing"
        Get-Job  | Remove-Job -Force
    }
    echo "still running"
    Start-Sleep -Seconds 3
}

PS:我的工作始于Start-Jobs已经处理好了..

6 个答案:

答案 0 :(得分:2)

我见过这个问题的唯一两个解决方案是:

  1. 将查询作为后台作业运行并为其设置计时器,然后停止/删除运行时间过长的作业。

  2. 修复服务器。

答案 1 :(得分:2)

您可以尝试发布here的get-wmiCustom函数。如果get-wmiObject有超时参数会不会很好?让我们upvote this thing

答案 2 :(得分:2)

答案 3 :(得分:1)

除了已经说过的,不是防弹解决方案,而是考虑首先ping你的服务器(Test-Connection),它可以加快执行时间,以防你没有响应的机器。

答案 4 :(得分:0)

使用get-wmiobject创建作业时,将该作业分配给变量,然后该变量可以通过管道传输到get-job for status或receive-job for results

$ThisJob = start-job -scriptblock {param ($Target) Get-WmiObject -Class Win32_Service -ComputerName $Target -AsJob} -ArgumentList $server
$Timer = [System.Diagnostics.Stopwatch]::StartNew()
While ($ThisJob | Get-Job | where {$_.State -imatch "Running"}){
    If ($Timer.Elapsed.Seconds -ge 5) {
        echo "five seconds has passed, removing"
        $ThisJob | Get-Job | Remove-Job -Force
        } # end if
    echo "still running"
    Start-Sleep -Seconds 3
    } # end while

$Results = $ThisJob | where {$_.State -inotmatch "failed"} | receive-job
$Timer.Stop | out-null

答案 5 :(得分:0)

我修改了Daniel Muscetta的Get-WmiCustom以支持传递凭证。

我知道这篇文章有点老了,希望这有助于其他人。

# Define modified custom get-wmiobject for timeout with credential from http://blogs.msdn.com/b/dmuscett/archive/2009/05/27/get_2d00_wmicustom.aspx
Function Get-WmiCustom([string]$Class,[string]$ComputerName,[string]$Namespace = "root\cimv2",[int]$Timeout=15, [pscredential]$Credential) 
{ 
    $ConnectionOptions = new-object System.Management.ConnectionOptions
    $EnumerationOptions = new-object System.Management.EnumerationOptions

    if($Credential){
        $ConnectionOptions.Username = $Credential.UserName;
        $ConnectionOptions.SecurePassword = $Credential.Password;
    }


    $timeoutseconds = new-timespan -seconds $timeout 
    $EnumerationOptions.set_timeout($timeoutseconds)

    $assembledpath = "\\$Computername\$Namespace"
    #write-host $assembledpath -foregroundcolor yellow

    $Scope = new-object System.Management.ManagementScope $assembledpath, $ConnectionOptions 
    $Scope.Connect()

    $querystring = "SELECT * FROM " + $class 
    #write-host $querystring

    $query = new-object System.Management.ObjectQuery $querystring 
    $searcher = new-object System.Management.ManagementObjectSearcher 
    $searcher.set_options($EnumerationOptions) 
    $searcher.Query = $querystring 
    $searcher.Scope = $Scope

    trap { $_ } $result = $searcher.get()

    return $result 
}