需要帮助解决 Array 和 Scriptblock 问题 或者也许使用参数和函数会更好???
脚本目标:轻松更新要安装的应用程序列表
出现以下错误。
'
在 C:\Temp\appinstall.ps1:7 字符:10
$Firefox={
~
赋值表达式无效。赋值运算符的输入必须是能够接受的对象
赋值,例如变量或属性。
+ 类别信息:ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : InvalidLeftHandSide
'
Start-Transcript -Append c:\Deploy\log.txt
$ProgressPreference = 'SilentlyContinue';
#Change App Name, Source, MSI/EXE, Argument
$AppArray= (
$Firefox={
$App= "Firefox";
$App_source= "https://download.mozilla.org/?product=firefox-latest&os=win64&lang=en-US";
$destination = "c:\Deploy\$App.exe";
$Argument= "/S";
},
$Chrome=
{
$App= "Chrome";
$App_source= "https://dl.google.com/tag/s/defaultbrowser/edgedl/chrome/install/GoogleChromeStandaloneEnterprise64.msi";
$destination = "c:\Deploy\$App.exe";
$Argument= "/norestart","/qn";
}
)
$InstallScriptBlock=
{
$installed = (Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where { $_.DisplayName -Match "$App" });
$installed.displayname
if ($installed.displayname -Match $App) {
Write-Host "$software installed"
}else{
If ((Test-Path $destination) -eq $false) {
New-Item -ItemType File -Path $destination -Force
}
#install software
Invoke-WebRequest $App_source -OutFile $destination
Start-Process -FilePath "$destination" -ArgumentList "$Argument" -Wait
#Delete installer
Remove-Item -recurse "$destination"
}
}
ForEach ($Program in $AppArray) {Invoke-Command -ScriptBlock $InstallScriptBlock}
Stop-Transcript
最佳答案
看起来您正在尝试创建一个嵌套的 hashtable (@{ ... }
),但您的语法有缺陷 - 请参阅链接文档。
但是:
在您的情况下,创建哈希表的数组 以使用
进行迭代就足够了foreach
无需使用单独的 script block (
{ ... }
) - 只需使用foreach
的正文循环语句。- 顺便说一句:在使用
Invoke-Command
时对于脚本 block 的本地调用,通常没有必要,因为&
,call operator , 会做(例如$sb = { 'hi' }; & $sb
)。Invoke-Command
的主要目的是在远程机器上 执行脚本 block 。
- 顺便说一句:在使用
通常,您可以按原样使用变量作为命令参数,而无需将它们包含在
"..."
中 - 即使它们的值包含空格。例如,Write-Output $foo
就足够了,不需要Write-Output "$foo"
综合起来:
# Create an array whose elements are hashtables.
$appArray = (
@{
App = ($thisApp = 'Firefox')
App_source = 'https://download.mozilla.org/?product=firefox-latest&os=win64&lang=en-US'
Destination = "c:\Deploy\$thisApp.exe"
Argument = '/S'
},
@{
App = ($thisApp = 'Chrome')
App_source = 'https://dl.google.com/tag/s/defaultbrowser/edgedl/chrome/install/GoogleChromeStandaloneEnterprise64.msi'
Destination = "c:\Deploy\$thisApp.exe"
Argument = '/norestart /qn'
}
)
foreach ($app in $appArray) {
# Note how $app.<key> is used to refer to the entries of the hashtable at hand,
# e.g. $app.App yields "Firefox" for the first hashtable.
$installed = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object { $_.DisplayName -Match $app.App }
$installed.displayname
if ($installed.displayname -Match $app.App) {
Write-Host "$($app.App) already installed."
}
else {
if ((Test-Path $app.Destination) -eq $false) {
New-Item -ItemType File -Path $app.Destination -Force
}
#install software
Invoke-WebRequest $app.App_source -OutFile $app.Destination
Start-Process -FilePath $app.Destination -ArgumentList $app.Argument -Wait
#Delete installer
Remove-Item -Recurse $app.Destination
}
}
注意:
我删除了不必要的
;
并改用 verbatim (single-quoted) strings ('...'
) 当没有通过 expandable (double-quoted) strings 进行字符串插值时("..."
) 是必需的,既是为了概念清晰,也是为了避免可能不需要的扩展。注意辅助的使用。
App
键中的变量$thisApp
,允许在后面的Destination
键中引用它,在可扩展字符串中("c:\Deploy\$thisApp.exe"
).- GitHub suggestion #13782寻找一种更优雅的方式来允许哈希表条目相互引用。
关于arrays - 使用数组和脚本 block 安装多个应用程序的 Powershell 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71424559/