Тайм-аут тестового пути для PowerShell - PullRequest
1 голос
/ 13 марта 2020

Я пытаюсь регулярно проверять наличие определенных строк в текстовых файлах на сотнях компьютеров в нашем домене.

foreach ($computer in $computers) {
    $hostname = $computer.DNSHostName
    if (Test-Connection $hostname -Count 2 -Quiet) {
        $FilePath = "\\" + $hostname + "c$\SomeDirectory\SomeFile.txt"
        if (Test-Path -Path $FilePath) {
            # Check for string
        }
    }
}

По большей части шаблон Test-Connection, а затем Test-Path эффективно и быстро. Однако есть определенные компьютеры, которые успешно пропингуют, но Test-Path занимает около 60 секунд, чтобы преобразовать в FALSE. Я не уверен, почему, но это может быть проблемой доверия к домену.

Для подобных ситуаций я хотел бы иметь тайм-аут для Test-Path, который по умолчанию равен FALSE, если это занимает более 2 секунд.

К сожалению, решение в связанном потоке ( Как мне обернуть этот командлет Powershell в функцию тайм-аута? ) не применимо к моей ситуации. Предлагаемое do-while l oop зависает в блоке кода.

Я экспериментировал с Джобсом, но, похоже, даже это не заставит выйти из команды Test-Path:

Start-Job -ScriptBlock {param($Path) Test-Path $Path} -ArgumentList $Path | Wait-Job -Timeout 2 | Remove-Job -Force

Работа продолжает зависать в фоновом режиме. Это самый чистый способ, которым я могу достичь своих требований выше? Есть ли лучший способ тайм-аута Test-Path, чтобы скрипт не зависал, кроме порождения асинхронных действий? Большое спасибо.

1 Ответ

3 голосов
/ 13 марта 2020

Оберните ваш код в объект [powershell] и вызовите BeginInvoke() для его асинхронного выполнения, затем используйте связанный WaitHandle, чтобы дождаться его завершения только в течение заданного промежутка времени.

$sleepDuration = Get-Random 2,3
$ps = [powershell]::Create().AddScript("Start-Sleep -Seconds $sleepDuration; 'Done!'")

# execute it asynchronously
$handle = $ps.BeginInvoke()

# Wait 2500 milliseconds for it to finish
if(-not $handle.AsyncWaitHandle.WaitOne(2500)){
    throw "timed out"
    return
}

# WaitOne() returned $true, let's fetch the result
$result = $ps.EndInvoke($handle)

return $result

В приведенном выше примере мы произвольно спим в течение 2 или 3 секунд, но устанавливаем тайм-аут на 2 с половиной секунды - попробуйте запустить его пару раз, чтобы увидеть эффект:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...