为什么这个 msiexec.exe 命令在 powershell 中不起作用?

Kev*_*ner 4 powershell windows-installer mongodb

我正在尝试通过 powershell 在高级安装程序生成的安装程序调用的脚本中执行以下命令。问题在于,当脚本执行时,它在调用 MSIEXEC.exe 时窒息。更具体地说,它会显示 msiexec 帮助屏幕的 Windows 对话框。

好吧,也许它不喜欢高级安装程序执行它的方式。所以我采取了导致问题的实际路线:

msiexec.exe /q /i 'C:\Users\ADMINI~1\AppData\Local\Temp\mongo-server-3.4-latest.msi' INSTALLLOCATION='C:\Program Files\MongoDB\Server\3.4\' ADDLOCAL='all'
Run Code Online (Sandbox Code Playgroud)

当我直接在 powershell 中执行这个时,我仍然得到同样愚蠢的帮助屏幕。我已经尝试了这个命令行的所有可能的变体:

  • /a 和 /passive 而不是 /i 和 /q
  • 带双引号
  • 带单引号
  • 未引用的 msi
  • 在管理员提升的 shell 中
  • 在普通特权 shell 中
  • 位于桌面上的 msi 而不是临时文件夹
  • 如果已经安装,使用 /x 卸载

在所有情况下,我都会看到该死的“帮助”对话框。唯一似乎有所不同的是我是否省略了 INSTALLLOCATION 和 ADDLOCAL 选项。(这些显然是按照此处找到的“无人值守安装第 2 部分”使用:https : //docs.mongodb.com/tutorials/install-mongodb-on-windows/)。在这种情况下,它只是安静地退出而不安装任何东西。

老实说,我整个下午都在用头撞墙。

顺便说一下,我以如此荒谬的方式安装 mongo 的原因是我需要一种方法来为我公司的产品安装单一安装系统。这取决于 Mongo,我们必须让它作为服务器运行并使用身份验证,所以我必须有脚本来创建管理员和数据库用户并将其置于身份验证模式。由于我需要知道 mongo 的安装位置(以执行 mongod.exe 和 mongo.exe),因此我需要先向用户查询位置,然后将安装位置传递给 mongo 安装程序。如果我在这里完全偏离轨道,请告诉我有更好的方法。谢谢

编辑:我忘了提到我编写了完整的 powershell 脚本并在尝试通过高级安装程序执行它之前对其进行了测试。该脚本一直有效,直到我尝试通过安装程序运行它。奇怪的是我现在仍然无法手动执行命令。

mkl*_*nt0 5

似乎为了将带有嵌入空格的路径传递给msiexec,您必须在它们周围使用显式嵌入 "..."引用。

在您的情况下,这意味着
INSTALLLOCATION='C:\Program Files\MongoDB\Server\3.4\'您必须通过[1]而不是通过INSTALLLOCATION='"C:\Program Files\MongoDB\Server\3.4\\"'

注意路径末尾的内嵌"..."和额外的\,以确保\"单独的不会被误认为是转义 "msiexec(尽管它也可以在没有额外的情况下工作\)。

把它们放在一起:

msiexec.exe /q /i `
  'C:\Users\ADMINI~1\AppData\Local\Temp\mongo-server-3.4-latest.msi' `
  INSTALLLOCATION='"C:\Program Files\MongoDB\Server\3.4\\"' ADDLOCAL='all'
Run Code Online (Sandbox Code Playgroud)

警告

  • 这种嵌入式引用技术依赖于长期存在但已损坏的PowerShell 行为- 请参阅此答案;如果它得到修复,该技术将停止工作;相比之下,
    --%下面显示的方法将继续有效。

  • 一个免费的解决方法-,面向未来的方法是使用PSv3 +ie辅助功能Native模块(在PSv5 +,与安装Install-Module NativePowerShell的图库),其内部补偿所有不正常的行为,并允许传递参数的预期; 也就是说,简单地添加ie到您的原始命令就足够了:

# No workarounds needed with the 'ie' function from the 'Native' module.
ie msiexec.exe /q /i 'C:\Users\ADMINI~1\AppData\Local\Temp\mongo-server-3.4-latest.msi' INSTALLLOCATION='C:\Program Files\MongoDB\Server\3.4\' ADDLOCAL='all'
Run Code Online (Sandbox Code Playgroud)

替代是坚持原来的报价和使用--%,将停止解析符号,但请注意,这意味着你不能在所有的后续参数使用PowerShell变量:

msiexec.exe /q /i `
  'C:\Users\ADMINI~1\AppData\Local\Temp\mongo-server-3.4-latest.msi' `
   --% INSTALLLOCATION="C:\Program Files\MongoDB\Server\3.4\\" ADDLOCAL='all'
Run Code Online (Sandbox Code Playgroud)

请注意msiexec,尽管有 CLI(命令行界面),但它是一个GUI子系统应用程序,因此默认情况下异步运行的;如果要同步运行,请使用
Start-Process -Wait

$msiArgs = '/q /i "C:\Users\ADMINI~1\AppData\Local\Temp\mongo-server-3.4-latest.msi" INSTALLLOCATION="C:\Program Files\MongoDB\Server\3.4\\" ADDLOCAL=all'

$ps = Start-Process -PassThru -Wait msiexec -ArgumentList $msiArgs

# $ps.ExitCode contains msiexec's exit code.
Run Code Online (Sandbox Code Playgroud)

注意,参数列表字符串$msiArgs,用于按原样通过Start-Process作为命令行的一部分用于调用目标程序(msiexec),这意味着:

  • 只能使用(嵌入的)双引号

    • "..."与嵌入式"转义`"一起使用以在字符串中嵌入 PowerShell 变量和表达式。
  • 然而,相反,不需要部分引用参数的解决方法。

尽管Start-Process技术上支持将参数作为数组单独传递,但由于长期存在的错误,最好避免这种情况 - 请参阅GitHub 问题 #5576


[1]INSTALLLOCATION='C:\Program Files\MongoDB\Server\3.4\'不起作用的原因是 PowerShell 通过"..."-quoting作为一个整体来转换参数,它msiexec无法识别;具体来说,msiexec在这种情况下传递给的是:
"INSTALLLOCATION=C:\Program Files\MongoDB\Server\3.4\"