【问题标题】:MSIEXEC - Argumentlist with VariableMSIEXEC - 带变量的参数列表
【发布时间】:2021-07-09 06:41:39
【问题描述】:

我正在尝试通过 msiexec 开始安装。 以下参数可用,如果我以这种方式使用它,安装将是正确的。 这是来自供应商的示例:

msiexec.exe /i ApexOne.msi MyServer="win2016-x64:8080|4343" MyDomain="Workgroup\Subdomain" /Lv+ "c:\temp\MSI.log"

这是我的代码:

Start-Process -FilePath "$env:systemroot\system32\msiexec.exe" -ArgumentList @('/i ".\agent.msi" MyServer="servername:8080|4344" MyDomain="999-Test"') -wait

但为了自动化,我必须使用变量 $domain 来生成正确的域。 我尝试了不同的代码,但没有任何帮助:

这是我的变量 $domain 的代码 $domain='999-Test'

示例: Start-Process -FilePath "$env:systemroot\system32\msiexec.exe" -ArgumentList @('/i ".\agent.msi" MyServer="servername:8080|4344" MyDomain=**"$domain"'**) -wait

我也试过了,但我不知道如何解决这个故障。 我认为变量的解释是错误的,但我无法修复它。

-ArgumentList @('/i ".\agent.msi"','MyServer="servername:8080|4344"','MyDomain='$domain'')

也许有人可以帮我解决这个错误?

【问题讨论】:

  • 单引号将字符串视为文字字符串而不进行插值(变量和表达式替换)。您需要将外部' 替换为" - 所以"MyDomain='$domain'"。请注意,如果有任何双引号inside,您还需要使用反引号转义字符串(例如"MyDomain=`"$domain`"")。
  • 我用过这个,但是不行:@('/i ".\agent.msi" MyServer="servername:8080|4344" MyDomain=`"$domain`"') -wait
  • 有了这个安装没有开始,缺少终止符'。我:所以我尝试了这个:``Start-Process -FilePath "$env:systemroot\system32\msiexec.exe" -ArgumentList @('/i ".\agent_vorlage.msi" MyServer="av01.badencloud.de: 8080|4344" "MyDomain="$domain""') -wait```
  • 您在混合和错误匹配单引号和双引号 - 这是行不通的。试试-ArgumentList @("/i `".\agent_vorlage.msi`" MyServer=`"av01.badencloud.de:8080|4344`" MyDomain=`"$domain`"")。整个字符串被双引号 " 包围,引号 insidebacktick double-quote 转义 - 即 `"
  • 今天略读一下,maybe have a look here

标签: powershell windows-installer


【解决方案1】:
  • 由于Start-Process 中的一个长期存在的错误,实际上最好始终将目标进程的所有参数编码在单个字符串中传递给-ArgumentList(@ 987654327@),而不是单独,作为数组的元素 - 请参阅this answer

  • 这样做需要两件事:

    • 要合并变量值,您必须使用expandable string,即引号字符串"..."

    • 任何嵌入引用inside这个整体"..."字符串必须本身使用-引用只有,因为 Windows 上的 CLI 通常只理解 "(双引号)而不是 '(单引号)来具有 语法 功能。要将" 字符嵌入"..." 字符串中,将它们转义为`"(或"";在'...' 字符串中,您根本不需要转义它们)。

虽然这有点麻烦,但它确实具有优点,允许您直接控制目标进程将看到的确切命令行 - 并且可以让您满足msiexec 的挑剔语法要求,其中 PROP="value with spaces" 必须完全使用这个仅值双引号传递(而 PowerShell - 有理由 - 在幕后将此参数转换为 "PROP=value with spaces",当它 - 必要时 - 重新引用 参数以合成要使用的实际命令行)。

因此,请使用以下内容(分别使用 positional 参数绑定到 -FilePath-ArgumentList):

Start-Process -Wait $env:systemroot\system32\msiexec.exe "/i .\agent.msi MyServer=`"servername:8080|4344`" MyDomain=`"999-Test`""

注意:严格来说,您的情况不需要嵌入的 `"...`" 引用,因为您的属性值没有嵌入的空格

【讨论】:

  • 感谢这些关于 msiexec.exe 问题的 Powershell 提示。我在我的experimental deployment information grid 中添加了您的一些答案 - 这样我就可以轻松找到它们。
  • 我很高兴听到它,@SteinÅsmul - 看起来像是一个方便的信息集合。
  • 它仍然是实验性的,但它时不时会有很大帮助——尤其是当您在一台没有所有其他工具可用的机器上时。
【解决方案2】:

msiexec.exe 程序的命令行解析器似乎有一些特殊性。我推荐如下方法:

$msiFileName = ".\agent.msi"
$myServer = "servername:8080|4344"
$myDomain = "999-Test"
$argumentList = @(
  '/i'
  '"{0}"' -f $msiFileName
  'MyServer="{0}"' -f $myServer
  'MyDomain="{0}"' -f $myDomain
)
$startArgs = @{
  "FilePath" = "msiexec.exe"
  "ArgumentList" = $argumentList
  "Wait" = $true
}
Start-Process @startArgs

此示例使用单引号 (') 和字符串格式 (-f) 为 -ArgumentList 参数创建一个字符串参数数组。在上面的示例中,$argumentList 数组中的每个元素都是一个单独的字符串,并且包含以下元素:

/i
".\agent.msi"
MyServer="servername:8080|4344"
MyDomain="999-Test"

(请注意,在数组的内容中,我们保留了 " 字符。)

接下来,我们为Start-Process cmdlet 创建一个哈希表,并使用@ 运算符调用它。 (为 cmdlet 的参数创建哈希表称为 splatting,这是一种以更易读和可维护的方式为 cmdlet 构建大量参数的便捷方法。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 2015-06-08
    • 2012-10-01
    相关资源
    最近更新 更多