Скрипт Powershell зависает, не завершается при вызове из командного файла - PullRequest
34 голосов
/ 11 января 2010

У меня есть сценарий PowerShell, который подключается к веб-сайту и анализирует его возвращенные данные (речь идет об импорте ранее загруженного файла SQL в базу данных веб-сайта). Сценарий PowerShell использует wget, что позже я могу заменить собственной функцией.

Процесс импорта встроен в скрипт, который выполняется сторонней программой с именем scriptFTP .

Сценарий работает нормально, когда я вызываю его из одного файла .bat, например:

powershell  "& "C:\data\etc\run_import_script.ps1"
exit %ERRORLEVEL%

Однако, когда я вызываю этот .bat-файл из большего контекста ScriptFTP, происходит следующее:

  • Сценарий PowerShell выполняется . Я подтвердил это, отправляя себе электронное письмо каждый раз, когда вызывался скрипт удаленного импорта.
  • Кажется, что PowerShell не завершается, и выполнение скрипта застревает . Я все еще могу отменить все это, используя Ctrl + C, но следующие команды никогда не будут выполнены.

Когда я изменяю командный файл на следующее:

start powershell  "& "C:\data\etc\run_import_script.ps1"
exit %ERRORLEVEL%

это работает , при запуске сценария PowerShell в новой консоли, но я не могу получить уровень ошибки, который возвращает PowerShell.

Я пытался вызвать PowerShell напрямую из ScriptFTP, минуя командный файл, но с тем же результатом: он просто зависает.

Все выходные данные, которые у меня есть в скрипте PowerShell, с использованием Write-Output или Write-Host, не отображаются.

Все программы запускаются под одним и тем же пользователем, мной.

У кого-нибудь есть идеи, что делать?

Ответы [ 10 ]

22 голосов
/ 03 апреля 2011

Этот вариант может работать для вас.

powershell -NoProfile -Command "C:\data\etc\run_import_script.ps1; exit $LASTEXITCODE" < NUL

Взято из http://thepowershellguy.com/blogs/posh/archive/2008/05/20/hey-powershell-guy-how-can-i-run-a-powershell-script-from-cmd-exe-and-return-an-errorlevel.aspx

16 голосов
/ 29 сентября 2014

По моему опыту, PowerShell.exe может легко запускать сценарии из командного файла или сценария оболочки предсказуемым образом с помощью ключа -File. Не нужно использовать команду «Пуск».

Важно сделать следующее:

< nul

в командную строку из командного файла. Мои исследования показали, что PowerShell выполняет команды в сценарии, указанном с помощью переключателя -File , а затем ожидает дополнительных команд PowerShell от стандартного ввода (мои краткие эксперименты с переключателем -Command показали аналогичное поведение). Перенаправляя стандартный ввод в nul, когда PowerShell заканчивает выполнение сценария и «читает конец файла» из стандартного ввода, PowerShell завершает работу.

При вызове PowerShell из Cygwin используйте

< /dev/null

Например, я запускал сценарии PowerShell из Cygwin с использованием переменных оболочки, например:

PowerShell.exe -ExecutionPolicy RemoteSigned -File $_powershellscriptpath $_firstscriptparameter < /dev/null

Пожалуйста, оставьте комментарий, если ваш опыт отличается от моего. - Гордон

16 голосов
/ 11 января 2010

Попробуйте добавить параметр / WAIT. Это заставит .bat ожидать завершения сценария PowerShell.

START /WAIT powershell "& "C:\data\etc\run_import_script.ps1"
9 голосов
/ 26 августа 2015

У нас была похожая проблема. Мы хотели вызвать приложение powershell из части программного обеспечения, в которой было только поле для ввода «Command» и «Parameters», но хотя powershell работало успешно (я мог видеть файл обновлен.)

Наконец мой коллега помог мне разобраться Команда должна быть:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe 

А Параметры:

-ExecutionPolicy unrestricted -Command "& {C:\scripts\apps\EDI\Test.ps1; [Environment]::Exit(1)}"

В нашем случае было важно использовать [Environment]::Exit(1) вместо Exit 1. Я считаю, что Exit просто завершал сценарий, а не закрывал Powershell .

2 голосов
/ 26 сентября 2014

Если вы хотите получить выходные данные команд powershell.exe, вы также можете использовать параметр / B для принудительного запуска процесса в командной оболочке same .

Мы только что видели очень странный случай этой проблемы. Пакетный файл, содержащий вызов powershell.exe -command ..., работал нормально локально, но останавливался, как описано выше, когда пакетный файл запускался в контексте команды msdeploy -postSync. После экспериментов с process.Kill(), чтобы заставить PowerShell завершить работу, мы остановились на использовании START /WAIT /B PowerShell.exe ..

Не знаю, почему это должно работать, но оно работает ...

1 голос
/ 07 апреля 2011

ЕСЛИ это именно то, что находится в вашем файле, это потому, что вы не соответствовали кавычкам. Powershell ждет последней цитаты.

0 голосов
/ 24 марта 2015

Вы можете просто добавить команду 'exit' в конец скрипта .ps1 (или любой другой вариант завершения процесса, который вы пожелаете). Powershell продолжит работу в конце сценария, поскольку ему не было приказано завершить работу (при запуске в PS или ISE он будет автоматически завершаться в конце сценария, но не при запуске через оболочку DOS).

0 голосов
/ 10 февраля 2015

У меня была точная проблема, мы пытались интегрировать сценарии Power Shell в другую систему, и она продолжала выдавать ошибку времени ожидания.Вероятно, из-за проблемы, упомянутой Гордоном Смитом, его решение может сработать.Но я предпочитаю иметь полный контроль над моим скриптом из самого скрипта и не зависеть от способа его вызова.

$ pid встроен в переменную с PID.Ниже приведен конец текущего процесса powershell и оставлены другие нетронутыми.Таким образом, любой может назвать ваш скрипт как обычно, и он будет работать как положено.

Stop-Process $pid
0 голосов
/ 13 января 2015

Бьюсь об заклад, проблема в том, что процесс Powershell продолжает выполняться после выполнения сценария .Это означает, что он не вышел и, следовательно, нет кода выхода.У меня похожая проблема, когда я пытаюсь запустить скрипт Powershell из C #, который выполняет все по окончании, за исключением того, что он никогда не завершается ...

Хаки, но единственное решение, которое я нашел, это поставить Stop-Process -processname powershell в конце скрипта .ps1.Это убивает процесс PowerShell (и все окна PowerShell, которые вы, к сожалению, открыли), но, похоже, работает.Может работать и для вашего сценария.

0 голосов
/ 11 января 2010

PowerShell имеет, по крайней мере то, что я считаю, странное поведение при вызове таким способом. Короче говоря, он не обрабатывает аргументы командной строки, передаваемые в powershell.exe, как выполняемые сценарии. Вместо этого он рассматривает их как команду для запуска. Это потому, что по умолчанию для powershell.exe - -команда - см. Powershell.exe /? для дополнительной информации.

C:\>powershell "'Hello'"
Hello

Что вам нужно будет сделать, так это создать умную входную строку для «источника» сценария, который вы хотите запустить:

C:\>powershell ". .\test.ps1"
Hello, World!

Что касается выходных данных, как только вы правильно запустите сценарий, нужно просто захватить STDOUT или что-то еще, что подходит вашему сценарию.

Полный пример

test.bat

@echo off
powershell.exe ". .\test.ps1"

Test.ps1

"Hello, World!"

Вызвать команду:

test.bat > test.txt

И убедитесь, что вывод был захвачен:

C:\>type test.txt
Hello, World!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...