PowerShell Start-Process бесконечное выполнение установщика

У меня есть установщик Inno Setup, который работает в очень тихом режиме (он работает).

Но когда я запускаю установщик Inno Setup через сценарий PowerShell с правами администратора, я получаю бесконечное выполнение. Кроме того, следующий код сценария (SetEnvironmentVariable) не выполняется даже после успешной установки.

$installerArguments = $requiredInstallerArguments + $additionalInstallerArguments

Start-Process -FilePath $installerFile.FullName -ArgumentList $installerArguments -Wait

[Environment]::SetEnvironmentVariable('WebPort', (GetValueByKey -array $additionalInstallerArguments -key "/webport"), [EnvironmentVariableTarget]::Machine)

Почему это происходит и как это исправить?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
106
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Иногда мне приходится использовать метод .WaitForExit()

$Process = Start-Process -FilePath $installerFile.FullName -ArgumentList $installerArguments -PassThru
$Process.WaitForExit()

Start-Process ... -Wait ведет себя иначе, чем (Start-Process ... -PassThru).WaitForExit() / Start-Process ... -PassThru | Wait-Process: первый ждет завершения всего дерева дочерних процессов, тогда как второй возвращается после завершения непосредственного дочернего процесса (см. Проблема GitHub № 15555). Таким образом, если установщик порождает дочерний процесс, который продолжает работать после выхода из установщика, -Wait не вернется, пока этот дочерний процесс не завершится.

В SysInternals Process Monitor вы можете использовать Инструменты->Дерево процессов, чтобы просмотреть эти деревья процессов.

В дополнение к полезному ответу Prodige69:

Другой способ дождаться только msiexec.exe (и дочерних процессов, запускаемых из него синхронно, если таковые имеются), а не всего его дочернего дерева процессов (msiexec.exe плюс любые дочерние процессы, запущенные из него асинхронно, что и является причиной проблемы здесь), — использовать прямое вызов или вызов через cmd.exe /c:

Это синтаксически более простые альтернативы использованию (Start-Process ... -PassThru).WaitForExit() или Start-Process ... -PassThru | Wait-Process, которые также автоматически отражают код завершения процесса msiexec в автоматической переменной $LASTEXITCODE :

Примечание. Я использую msiexec.exe в примерах команд ниже, но то же самое применимо и к любому установщику; в вашем случае, при использовании техники прямого призыва, замените & $installerFile.FullName на msiexec, при использовании техники cmd.exe /c замените "$($installerFile.FullName)"

  • Использование прямого вызова с помощью трюка, позволяющего сделать вызов синхронным:
# To build an argument list *programmatically*, create an *array*
$installerArguments = '/i', 'sample.msi', '/qn'

# Executes *synchronously*, due to `| Out-Null`
# Process exit code is reported in $LASTEXITCODE afterwards.
# Equivalent of: 
#   msiexec /i sample.msi /qn | Out-Null
msiexec $installerArguments | Out-Null
  • Вызов через cmd /c, который позволяет явно управлять цитированием, что необходимо для значений свойств, требующих частичного цитирования:
# Here, encode all arguments in a *single string*, using embedded double-quoting.
$installerArgumentList = '/i sample.msi /qn PROP = "Value with spaces"'

# Executes *synchronously*, due to `cmd /c`
# Process exit code is reported in $LASTEXITCODE afterwards.
cmd /c "msiexec $installerArguments"

См. этот ответ для получения дополнительной информации.

Другие вопросы по теме