У меня создан следующий файл ps1:
$Tool = "pnpm"
$ArgumentList = "run", "build"
$processResult = Start-Process `
-FilePath $Tool `
-ArgumentList $ArgumentList `
-NoNewWindow `
-PassThru `
-Wait
Если я попытаюсь запустить его в PowerShell, например: .\example.ps1
Я получил следующее сообщение об ошибке:
Start-Process: C:\data\example.ps1:3
Line |
3 | $processResult = Start-Process `
| ~~~~~~~~~~~~~~~
| This command cannot be run due to the error: %1 is not a valid Win32 application.
Но если я запускаю тот же файл на Mac PowerShell, он работает успешно.
Кроме того, если я просто изменю pnpm на npm, он запустится.
Далее приведены версии моих приложений:
пнпм: 8.3.1 узел: 20.10.0 НПМ: 10.2.3 питон: 3.12.4 мощностьШел: 7.4.3
Есть идеи? Спасибо!
CommandType Имя Версия Источник ----------- ---- ------- ------ Внешний сценарий pnpm.ps1 C:\Users\user\AppData\Roaming\npm\pnp …
Вы используете pnpm
или @pnpm/exe
? Какое расширение у исполняемого файла pnpm
?
я использую пнпм
Хотя у меня нет объяснения сообщения об ошибке, обратите внимание: если pnpm
относится к pnpm.ps1
, вы не сможете выполнить его через Start-Process
(при конфигурации по умолчанию файл будет открыт для редактирования). Поскольку вы, по-видимому, хотите вызвать команду в том же окне синхронно, вы можете просто вызвать pnmp.ps1
напрямую: pnmp run build
. Таким образом, вы можете записать выходные данные, а $LASTEXITCODE
впоследствии отразит код завершения процесса. См. этот ответ для получения дополнительной информации.
Мне нужно сделать это из файла ps1. Вы имеете в виду выполнить это прямо на консоли? ну, этот фрагмент кода является частью другого, более крупного, но я могу проверить, что вы имеете в виду, внося некоторые изменения в код
@rasilvap, он должен работать одинаково изнутри скрипта.
что-то вроде $Tool = "pnpm" $ArgumentList = "run", "build" & $Tool $ArgumentList $processResult = $LASTEXITCODE просто интересно поведение -wait, я собираюсь это проверить
Я добавил $Tool = "pnpm"; $ArgumentList = "запустить", "построить"; $result = & $Tool $ArgumentList Write-Host «результат: $LastExitCode», но не печатается LastExitCode
Могу ли я спросить что-то вроде if ($LASTEXITCODE -ne 0) { throw "Tool ($Tool) Failed!!!" } верно ?
Выполняем это: $Tool = "pnpm" $ArgumentList = @("run", "build") & $Tool @ArgumentList $processResult = $LASTEXITCODE Write-Host ` -ForegroundColor DarkYellow ` "результат: $( $LASTEXITCODE -eq 0 ? «УСПЕХ»: «НЕУДАЧА»). if ($LASTEXITCODE -ne 0) { throw «Инструмент ($Tool) не удался!!!» } Write-Host «Доблесть LastExitCode es: $processResult» ничего не печатает
Ваши симптомы несколько загадочны, но я предлагаю следующее:
Обновите pnpm до текущей версии, если это возможно — на момент написания этой статьи текущая версия v9.4.0, поэтому ваша версия довольно старая.
Убедитесь, что при выполнении pnpm
выполняется именно pnpm.exe
, а не файл pnmp.ps1
:
То есть Get-Command pnpm
должен указывать на файл *.exe
, обычно $HOME\AppData\Local\pnpm\pnpm.exe
; последний устанавливается при следовании официальным инструкциям по установке.
Напротив, как следует из вывода вашей системы, цитируемого в комментарии, в вашем случае pnmp
относится к файлу pnmp.ps1
.
Не говоря уже о том, является ли это официальной частью вашей pnpm
установки (возможно, это было в более ранних версиях, я не знаю), вы принципиально не можете напрямую выполнить .ps1
файл через Start-Process; вместо этого по умолчанию файл открывается для редактирования.
Я предлагаю удалить этот файл .ps1
, чтобы он не мешал вызову файла .exe
, что вы можете сделать с помощью (Get-Command pnpm.ps1).Path | Remove-Item -WhatIf
(удалите -WhatIf
, если вы уверены, что выбран правильный файл). В качестве альтернативы, явный вызов pnpm.exe
, т. е. с расширением .exe
, является специальным обходным решением.
Аргументы, которые вы передаете Start-Process
, предполагают, что вы хотите вызвать pnmp
синхронно, в текущей консоли (терминале). Однако для этого вам не нужен Start-Process
, а использование прямого вызова не только проще, но также позволяет вам перехватить выходные данные инструмента и отразить его код завершения в автоматической переменной $LASTEXITCODE . См. этот ответ для получения дополнительной информации.
В качестве отступления: файл *.exe
, по необходимости запущенный в дочернем процессе, неизменно сообщает код завершения (процесса), который впоследствии отражается в $LASTEXITCODE
.
PowerShell, напротив, запускает *.ps1
файлы сценариев в процессе, а $LASTEXITCODE
устанавливается тогда и только тогда, когда сценарий завершается с помощью вызова выхода с числовым аргументом (например, exit 1
). В противном случае любой ранее существовавший $LASTEXITCODE
, если таковой имеется, остается в силе (в исходном сеансе $LASTEXITCODE
изначально не определен). Если вы имеете дело со сценарием, о котором вы не знаете, устанавливает ли он код завершения, используйте следующую идиому: $global:LASTEXITCODE = $null; ./yourScript.ps1 ...; if ($null -ne $LASTEXITCODE) { <# implies that the exit code was deliberately set #> }
Поэтому я предлагаю следующее:
$Tool = "pnpm.exe"
$ArgumentList = "run", "build"
# Invoke pnpm synchronously, in the current console.
# * &, the call operator, is needed, because the command is specified
# via a variable.
# * @ArgumentList performs *splatting*, i.e. passes the array elements as
# individual arguments (in the case of *external programs* only, that
# would also happen with $ArgumentList)
& $Tool @ArgumentList
# Check the process exit code, reflected in $LASTEXITCODE.
if ($LASTEXITCODE) { throw "$Tool failed with exit code $LASTEXITCODE." }
Вероятно, вам потребуется установить или обновить версию pnpm.
pnpm install
Если у вас ОС Windows, убедитесь, что pnpm — это приложение.
Get-Command -Name 'pnpm'
Если это не приложение, переустановите pnpm по этой ссылке: https://pnpm.io/installation
Сработало, спасибо!
Каков результат
Get-Command -Name 'pnpm'
?