自动安装 .msi
Automate .msi installs
我正在尝试一个接一个地批量安装一堆 .msi。但是当我 运行 我的 powershell 脚本 msiexec /?好像我的论点是错误的。我在这里错过了什么?
$Path = Get-ChildItem -Path *my path goes here* -Recurse -Filter *.MSI
foreach ( $Installer in ( Get-ChildItem -Path $Path.DirectoryName -Filter *.MSI ) ) {
Start-Process -Wait -FilePath C:\windows\system32\msiexec.exe -ArgumentList "/i '$Installer.FullName'"
}
语法"/i '$Installer.FullName'"
不正确。在您的代码中应该是 "/i", $Installer.FullName
。
用双引号将 PowerShell 对象括起来会触发字符串扩展。当发生这种情况时,只有变量本身被替换为它的值,然后其余不属于名称的字符被视为字符串。当您 运行 以下片段时,您可以看到该对象执行了 ToString() ,然后将字符串 .FullName 添加到其中。
foreach ( $Installer in ( Get-ChildItem -Path $Path.DirectoryName -Filter *.MSI ) ) {
"/i $Installer.FullName"
}
如果您必须使用双引号,那么解决它的方法是使用 sub-expression 运算符 $()。解析器将内部的任何内容视为表达式。所以更详细的 "/i '$($Installer.FullName)'"
在技术上是可行的。
完整代码应该是:
$Path = Get-ChildItem -Path *my path goes here* -Recurse -Filter *.MSI
foreach ( $Installer in ( Get-ChildItem -Path $Path.DirectoryName -Filter *.MSI ) ) {
Start-Process -Wait -FilePath C:\windows\system32\msiexec.exe -ArgumentList "/i", $Installer.FullName
}
包含很好的建议,但让我试着从概念上归纳一下:
您的尝试有两个不相关的问题:
内部可扩展字符串("..."
)只能使用简单变量引用($Installer
)as-is; 表达式 ($Installer.FullName
) 需要 $()
,subexpression operator: $($Installer.FullName)
- see this answer 以获得 PowerShell 中可扩展字符串(字符串插值)的概述。
由于您通过 -ArgumentList
将 msiexec
的参数作为 单个字符串 传递,因此仅嵌入 支持双引号、"..."
,不支持'...'
(单引号)。
因此,使用以下内容(为简洁起见,-FilePath
和 -ArgumentList
参数按 位置 传递给 Start-Process
):
Get-ChildItem $Path.DirectoryName -Recurse -Filter *.MSI | ForEach-Object {
Start-Process -Wait C:\windows\system32\msiexec.exe "/i `"$($_.FullName)`""
}
注:
-ArgumentList
参数是数组类型的([string[]]
)。理想情况下,您会因此将参数 单独 作为数组的元素传递:'/i', $_.FullName
,这不需要您考虑 embedded 在 单个 字符串中引用。
不幸的是,Start-Process
doesn't handle such individually passed arguments properly if they contain embedded spaces,所以可靠的解决方案是使用 单个 -ArgumentList
包含 所有参数 个参数,根据需要 嵌入 double-quoting,,如上所示。
有关更详细的讨论,请参阅 。
在 Powershell 5.1 中,使用 msi,您还可以:
install-package $installer.fullname
我正在尝试一个接一个地批量安装一堆 .msi。但是当我 运行 我的 powershell 脚本 msiexec /?好像我的论点是错误的。我在这里错过了什么?
$Path = Get-ChildItem -Path *my path goes here* -Recurse -Filter *.MSI
foreach ( $Installer in ( Get-ChildItem -Path $Path.DirectoryName -Filter *.MSI ) ) {
Start-Process -Wait -FilePath C:\windows\system32\msiexec.exe -ArgumentList "/i '$Installer.FullName'"
}
语法"/i '$Installer.FullName'"
不正确。在您的代码中应该是 "/i", $Installer.FullName
。
用双引号将 PowerShell 对象括起来会触发字符串扩展。当发生这种情况时,只有变量本身被替换为它的值,然后其余不属于名称的字符被视为字符串。当您 运行 以下片段时,您可以看到该对象执行了 ToString() ,然后将字符串 .FullName 添加到其中。
foreach ( $Installer in ( Get-ChildItem -Path $Path.DirectoryName -Filter *.MSI ) ) {
"/i $Installer.FullName"
}
如果您必须使用双引号,那么解决它的方法是使用 sub-expression 运算符 $()。解析器将内部的任何内容视为表达式。所以更详细的 "/i '$($Installer.FullName)'"
在技术上是可行的。
完整代码应该是:
$Path = Get-ChildItem -Path *my path goes here* -Recurse -Filter *.MSI
foreach ( $Installer in ( Get-ChildItem -Path $Path.DirectoryName -Filter *.MSI ) ) {
Start-Process -Wait -FilePath C:\windows\system32\msiexec.exe -ArgumentList "/i", $Installer.FullName
}
您的尝试有两个不相关的问题:
内部可扩展字符串(
"..."
)只能使用简单变量引用($Installer
)as-is; 表达式 ($Installer.FullName
) 需要$()
,subexpression operator:$($Installer.FullName)
- see this answer 以获得 PowerShell 中可扩展字符串(字符串插值)的概述。由于您通过
-ArgumentList
将msiexec
的参数作为 单个字符串 传递,因此仅嵌入 支持双引号、"..."
,不支持'...'
(单引号)。
因此,使用以下内容(为简洁起见,-FilePath
和 -ArgumentList
参数按 位置 传递给 Start-Process
):
Get-ChildItem $Path.DirectoryName -Recurse -Filter *.MSI | ForEach-Object {
Start-Process -Wait C:\windows\system32\msiexec.exe "/i `"$($_.FullName)`""
}
注:
-ArgumentList
参数是数组类型的([string[]]
)。理想情况下,您会因此将参数 单独 作为数组的元素传递:'/i', $_.FullName
,这不需要您考虑 embedded 在 单个 字符串中引用。
不幸的是,Start-Process
doesn't handle such individually passed arguments properly if they contain embedded spaces,所以可靠的解决方案是使用 单个 -ArgumentList
包含 所有参数 个参数,根据需要 嵌入 double-quoting,,如上所示。
有关更详细的讨论,请参阅
在 Powershell 5.1 中,使用 msi,您还可以:
install-package $installer.fullname