В. Как приостановить PowerShell при выполнении процесса Win32 из Windows PowerShell, чтобы завершить процесс, прежде чем запускать другие команды PowerShell?

О. В этом можно убедиться, запустив программу Notepad: она выполняется, но управление немедленно передается в окно PowerShell.

При запуске консольного приложения PowerShell ожидает завершения консольного приложения, прежде чем продолжить работу. Таким образом, чтобы дождаться завершения процесса Win32, можно направить выход процесса в null, например, так:

notepad | out-null

При запуске этой команды управление не возвращается PowerShell до тех пор, пока пользователь не закроет экземпляр Notepad.

Другой способ: использовать метод Process.WaitForExit, чтобы PowerShell дожидался завершения процесса. Для этого необходимо получить ссылку на идентификатор процесса Win32, которого нужно дождаться. Идентификатор процесса можно попытаться получить, выполнив поиск имени процесса с помощью таких критериев, как заголовки окна (например, $tpid = get-process | where {$_.mainwindowtitle -match "notepad"}), но при этом могут возникать ошибки, если выполняется несколько процессов с одинаковым именем. Более удачный способ -- создать процесс с использованием метода start класса System.Diagnostics.Process в Microsoft .NET Framework, который возвращает идентификатор процесса при создании последнего, как в следующем примере:

PS C:UsersAdministrator> $tpid = [diagnostics.process]::start("notepad.exe")
PS C:UsersAdministrator> $tpid.WaitForExit()

После этого управление не будет возвращено PowerShell до тех пор, пока не будет закрыт экземпляр Notepad. Альтернатива предыдущему способу -- объединить команды в одну, например так:

[diagnostics.process]::start("notepad.exe").WaitForExit()

С использованием Process.WaitForExit можно также ввести максимальное время ожидания (в миллисекундах). Например, при запуске $tpid.WaitForExit(30000) ожидание длится до завершения процесса или 30 с (в зависимости от того, какое из этих событий произойдет первым). Если процесс закрывается в заданный период времени, то Process.WaitForExit возвращает значение TRUE; в противном случае возвращается значение FALSE.

Обратите внимание: если нужно передать параметры в процесс Win32, достаточно добавить их ко второму аргументу команды start. Например, чтобы запустить Notepad для редактирования файла c: empjohn.txt, можно использовать команду

[diagnostics.process]::start("notepad.exe","C: empjohn.txt").WaitForExit()

При этом необходимо указать полный путь к каждому параметру. Если нужно использовать только текущую рабочую папку, просто введите $pwd.