2016-02-01 2 views
3

У меня есть следующий сценарий для запуска приложения:PowerShell приложение ждать, чтобы запустить

add-type -AssemblyName microsoft.VisualBasic 
add-type -AssemblyName System.Windows.Forms 
$args = "arguments" 
$proc = Start-Process -PassThru "path" -ArgumentList $args 
start-sleep -Seconds 5 
[Microsoft.VisualBasic.Interaction]::AppActivate($proc.Id) 
[System.Windows.Forms.SendKeys]::SendWait("~") 

Я использую этот скрипт для запуска нескольких приложений Windows Forms, которые требуют взаимодействия с пользователем, чтобы начать (т.е. нажать кнопку пуска). До сих пор я спал сценарий 5 секунд, чтобы приложение запускалось. Я попытался запустить этот скрипт на разных компьютерах с различными возможностями обработки, но не работал на всех компьютерах, некоторые запускали приложение медленнее, чем другие, когда для приложения было занято более 5 секунд, чтобы запустить скрипт, потому что AppActivate не удалось найти PID. Я не хочу попробовать разные времена сна для каждого компьютера, потому что я должен запустить этот скрипт на более чем 100 компьютерах во время загрузки.

Я хотел бы знать, есть ли способ дождаться, когда приложение начнет запускать событие.

UPDATE:

WaitForInputIdle не работает во всех приложениях, которые я пытался начать. Он возвращается немедленно (успешно, потому что он возвращает true), и метод AppActive генерирует исключение.

+0

это поможет вам .... 'start-process -wait' (дождитесь завершения процесса) – Kiran

+0

Нет, потому что он ждет завершения процесса, прежде чем принимать больше ввода. Я должен спящий сценарий в течение 5 секунд, иначе функция AppActivate выдает исключение, потому что он не нашел идентификатор процесса. – rena

+0

Было бы потому, что вместо -Seconds это должно быть -s PS. idk, почему код не работает o_O –

ответ

3

Я предлагаю вам не использовать «Сон» для синхронизации системных объектов (это никогда не будет хорошим решением). По мере того, как вы запускаете приложение Windows Forms, я предлагаю вам использовать метод Process.WaitForInputIdle.

$p = [diagnostics.process]::start("notepad.exe", "D:\temp\1mbfile.txt") 
$p.WaitForInputIdle(5000); 

использовать его в цикле, вы можете проверить в качестве альтернативы тест, если вход находится в режиме ожидания (приложение запускается и ожидания), или если приложение остановлено ($p.HasExited -eq $true).

do 
{ 
    if ($p.HasExited -eq $true) 
    { 
    break 
    } 
} while ($p.WaitForInputIdle(5000) -ne $true) 
+0

Как я могу узнать с помощью этого цикла, когда процесс завершит создание своего главного окна и простаивает (приложение запущено и ожидает ввода пользователя)? – rena

+0

Я редактирую код, нормальный после цикла окна не работает. Вы должны проверить $ p.HasExited, чтобы убедиться, что процесс не вышел. – JPBlanc

+0

Да, я тестировал это так, но WaitForInputIdle не работает все время, некоторые приложения возвращаются промежуточно, и AppActivate дает мне ошибку (Process {0} не найден). Приложения - .net-приложения. – rena

1

Итак, я, наконец, написал это временное решение, так как WaitForInputIdle не работает со всеми моими приложениями, и я не мог понять, почему.

do{ 
    if ($proc.MainWindowHandle -ne 0) 
    { 
     break 
    } 
    $proc.Refresh() 
} while ($true) 

Я не уверен, что это лучший подход; во всяком случае, я хотел поделиться этим.

Смежные вопросы