通过 PowerShell 执行 cmd 命令时,如何查找执行的退出码?

8
我正在使用静默安装命令安装软件。我是在PowerShell 3.0中运行此命令。
$silentInstall = C:\Users\Admin\Documents\Setup-2.0.exe exe /s /v"EULAACCEPTED=\"Yes\" /l*v c:\install.log /qn"

Invoke-Expression $silentInstall

这会运行安装软件的命令,但它不等待完成就继续执行下面的代码。我想控制安装过程,以便知道它是否已经完成。
我该如何获取Invoke-Expression cmdlet的错误代码,以便我可以知道命令是否成功执行?

运行外部命令的章节和诗句:http://edgylogic.com/blog/powershell-and-external-commands-done-right/ - andyb
3个回答

24

这取决于EXE文件的运行方式 - 有时它会启动一个单独的进程并立即返回,这种情况下通常会起作用 -

$p = Start-Process -FilePath <path> -ArgumentList <args> -Wait -NoNewWindow -PassThru
$p.ExitCode
否则通常这个方法有效 -
& <path> <args>
$LASTEXITCODE

或者有时候是这样的 -

& cmd.exe /c <path> <args>
$LASTEXITCODE

1
当我不使用“Start-Process”方法时,$LASTEXITCODE是我所需要的。 - Jaans
1
+1 对于 cmd.exe /c 技巧 - 这是唯一能在运行 VC++ 安装程序时获取退出代码的方法。 - thomasb

3

您不应该需要使用Invoke-Expression:

& C:\Users\Admin\Documents\Setup-2.0.exe /s /vEULAACCEPTED=Yes /l*v C:\install.log /qn

这应该是被接受的答案。开箱即用,包括通过 $? 检索错误代码。 - Xlea
请注意,某些setup.exe文件(例如由Inno Setup生成的文件)在使用&运行时会立即返回。出于某种原因,我不得不使用Start-Process -Wait -PassThru... - Matthieu

3

看起来您正在运行一个MSI安装程序。当从控制台运行时,控制立即返回,而MSI分叉一个新进程来运行安装程序。没有方法可以更改此行为。

您可能需要使用Get-Process查找名为msiexec的进程,并等待其完成。始终有一个运行msiexec的进程,用于启动新的安装程序,因此您需要找到在您的安装开始后启动的msiexec进程。

$msiexecd = Get-Process -Name 'msiexec'
C:\Users\Admin\Documents\Setup-2.0.exe exe `
                                       /s `
                                       /v"EULAACCEPTED=\"Yes\" /l*v c:\install.log /qn"
$myMsi = Get-Process -Name 'msiexec' | 
             Where-Object { $_.Id -ne $msiexecd.Id }
$myMsi.WaitForExit()
Write-Verbose $myMsi.ExitCode

非常感谢,这真的很有帮助。这就是我在寻找的东西。我能够找到正在运行的msiexec进程,但我无法弄清如何获取退出代码(以查找安装是否成功)。 - user3543477

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接