Подтвердить что ты не робот

Powershell script застревает, не выходит при вызове из командного файла

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

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

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

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

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

  • Выполняется PowerShell script . Я подтвердил это, отправляя себе E-Mail каждый раз, когда вы вызывали удаленный импорт script.
  • PowerShell, похоже, не выходит, и выполнение script застревает. Я все еще могу отменить все это с помощью Ctrl + C, но следующие команды никогда не будут выполнены.

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

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

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

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

Любой вывод, который у меня есть, имеет PowerShell script, используя Write-Output или Write-Host.

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

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

4b9b3361

Ответ 1

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

START /WAIT powershell "& "C:\data\etc\run_import_script.ps1"

Ответ 3

Из моего опыта, 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

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

Ответ 4

У нас была аналогичная проблема. Мы хотели вызвать приложение 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.

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

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!

Ответ 8

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

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

Ответ 9

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

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

Stop-Process $pid

Ответ 10

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