Ответ 1
Попробуйте добавить параметр /WAIT. Он будет поддерживать .bat в ожидании завершения PowerShell script.
START /WAIT powershell "& "C:\data\etc\run_import_script.ps1"
У меня есть PowerShell script, который подключается к веб-сайту и анализирует его возвращенные данные (об импорте ранее загруженного файла SQL в базу данных веб-сайта). В PowerShell script используется wget
, что-то, что я могу заменить встроенной функцией позже.
Процесс импорта встроен в script, который выполняется сторонней программой под названием scriptFTP.
script отлично работает, когда я вызываю его из одного .bat файла, например:
powershell "& "C:\data\etc\run_import_script.ps1"
exit %ERRORLEVEL%
Однако, когда я вызываю этот .bat файл из большего контекста ScriptFTP, происходит следующее:
Когда я меняю пакетный файл на следующее:
start powershell "& "C:\data\etc\run_import_script.ps1"
exit %ERRORLEVEL%
он работает, запустив PowerShell script в новой консоли, но я не могу получить уровень ошибок, который возвращает PowerShell.
Я попытался напрямую вызвать PowerShell из ScriptFTP, минуя командный файл, но с тем же результатом: он просто застревает.
Любой вывод, который у меня есть, имеет PowerShell script, используя Write-Output
или Write-Host
.
Все программы работают под одним и тем же пользователем, я.
Есть ли у кого-нибудь идеи, что делать?
Попробуйте добавить параметр /WAIT. Он будет поддерживать .bat в ожидании завершения PowerShell script.
START /WAIT powershell "& "C:\data\etc\run_import_script.ps1"
Этот вариант может работать для вас.
powershell -NoProfile -Command "C:\data\etc\run_import_script.ps1; exit $LASTEXITCODE" < NUL
Из моего опыта, PowerShell.exe может легко запускать сценарии из пакетного файла или оболочки script предсказуемым образом с помощью переключателя -File. Не нужно использовать команду "Пуск".
Важная вещь - добавить
< nul
в командной строке из командного файла. Мои исследования показали, что PowerShell запускает команды в script, указанные с помощью переключателя -File , а затем ждет дополнительных команд PowerShell со стандартного ввода (мои краткие эксперименты с переключателем -Command показали аналогичное поведение). Перенаправив стандартный ввод в nul, как только PowerShell завершит выполнение script и "читает конец файла" со стандартного ввода, PowerShell завершает работу.
При вызове PowerShell из Cygwin используйте
< /dev/null
Например, я запускал сценарии PowerShell из Cygwin с использованием переменных оболочки, например:
PowerShell.exe -ExecutionPolicy RemoteSigned -File $_powershellscriptpath $_firstscriptparameter < /dev/null
Пожалуйста, напишите комментарий, если ваш опыт изменился от моего. - Гордон
У нас была аналогичная проблема. Мы хотели вызвать приложение 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
. Я полагаю, что Выход просто завершает script, не закрывая Powershell.
Если вы хотите захватить вывод команд powershell.exe, вы также можете использовать параметр /B, чтобы заставить процесс работать в командной строке ..
Мы только что видели очень странный экземпляр этой проблемы. Пакетный файл, содержащий вызов powershell.exe -command ...
, выполнялся нормально локально, но был остановлен, как описано выше, когда командный файл запускался в контексте команды msdeploy -postSync. После экспериментов с process.Kill()
, чтобы заставить PowerShell выйти, мы зажгли использование START /WAIT /B PowerShell.exe ..
Не знаю, почему это должно сработать, но оно...
ЕСЛИ это именно то, что в вашем файле, потому что у вас есть несогласованные кавычки. Powershell ждет последней цитаты.
PowerShell имеет, по крайней мере, то, что я считаю, странное поведение при вызове таким образом. Короче говоря, он не обрабатывает аргументы командной строки, передаваемые powershell.exe в качестве сценариев для запуска. Вместо этого он рассматривает их как команду для запуска. Это связано с тем, что по умолчанию для powershell.exe является -command - см. Powershell.exe/? для дополнительной информации.
C:\>powershell "'Hello'"
Hello
Что вам нужно сделать, это построить умную входную строку для "источника" script, которую вы хотите запустить:
C:\>powershell ". .\test.ps1"
Hello, World!
Как и для вывода, как только вы выполняете корректную работу script, это должно быть просто вопросом захвата STDOUT или чего-то другого, заканчивающегося вашим script.
Полный пример
test.bat
@echo off
powershell.exe ". .\test.ps1"
Test.ps1
"Hello, World!"
Вызвать команду:
test.bat > test.txt
И убедитесь, что результат был захвачен:
C:\>type test.txt
Hello, World!
Проблема, которую я поставил, заключается в том, что процесс Powershell продолжает работать после выполнения script. Это означает, что он не вышел и, следовательно, отсутствует код выхода. У меня есть аналогичная проблема при попытке запустить Powershell script из С#, который делает что-то, когда закончится, за исключением того, что он никогда не заканчивается...
Hacky, но единственное решение, которое я нашел, - положить Stop-Process -processname powershell
в конец .ps1 script. Это убивает процесс PowerShell (и все окна PowerShell, которые вы открываете, к сожалению), но, похоже, работает. Может работать и для вашего script.
У меня была точная проблема, мы пытались интегрировать сценарии оболочки оболочки в другую систему, и она продолжала давать ошибку таймаута. Вероятно, из-за проблемы, упомянутой Гордоном Смитом, его решение может работать. Но для меня я предпочитаю полностью контролировать свой script из самого script и не зависеть от способа его вызова.
$pid встроен в переменную с PID. Нижеследующее завершает текущий процесс powershell и оставляет остальных неповрежденными. Таким образом, любой может вызвать ваш script как обычно, и он будет работать, как ожидалось.
Stop-Process $pid
вы можете просто добавить команду "exit" в конец .ps1 script (или любой вариант завершения процесса, который вы хотите). Powershell продолжит работу в конце script, поскольку ему не сказали прекратить (при запуске в PS или ISE он будет автоматически завершаться в конце script, но не при запуске через оболочку DOS).