简体   繁体   English

Powershell 使用数组和脚本块安装多个应用程序的脚本

[英]Powershell script to install multiple applications using an array and scriptblock

Need help troubleshooting an the Array and Scriptblock OR Maybe this is better using param and functions???需要帮助解决 Array 和 Scriptblock 问题,或者使用参数和函数可能更好???

Script Objective: To easily update the list of applications to be installed脚本目标:轻松更新要安装的应用程序列表

Getting error below.在下面出现错误。

' At C:\Temp\appinstall.ps1:7 char:10 $Firefox={ ' 在 C:\Temp\appinstall.ps1:7 char:10 $Firefox={
~ The assignment expression is not valid. ~ 赋值表达式无效。 The input to an assignment operator must be an object that is able to accept assignments, such as a variable or a property.赋值运算符的输入必须是能够接受赋值的 object,例如变量或属性。 + CategoryInfo: ParserError: (:) [], ParseException + FullyQualifiedErrorId: InvalidLeftHandSide ' + CategoryInfo: 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

It looks like you're trying to create a nested hashtable ( @{... } ), but your syntax is flawed - see the linked docs.看起来您正在尝试创建一个嵌套的哈希表@{... } ),但您的语法有缺陷 - 请参阅链接文档。

However:然而:

  • It should suffice in your case to create an array of hashtables to iterate over with foreach在您的情况下,创建一个哈希表数组以使用foreach进行迭代就足够了

  • There's no need to use a separate script block ( {... } ) - just use the body of the foreach loop statement.无需使用单独的脚本块( {... } ) - 只需使用foreach循环语句的主体即可。

    • As an aside: While using Invoke-Command for local invocation of script blocks works, it usually isn't necessary, because & , the call operator , will do (eg $sb = { 'hi' }; & $sb ).顺便说一句:虽然使用Invoke-Command来本地调用脚本块是可行的,但通常没有必要,因为&调用运算符,会这样做(例如$sb = { 'hi' }; & $sb )。 Invoke-Command 's primary purpose is to execute a script block on a remote machine . Invoke-Command的主要目的是在远程机器上执行脚本块。
  • Generally, you can use variables as-is as command arguments, without enclosing them in "..." - even if their values contain spaces.通常,您可以按原样使用变量作为命令 arguments,无需将它们括在"..."中 - 即使它们的值包含空格。 Eg, Write-Output $foo is sufficient, no need for Write-Output "$foo"例如, Write-Output $foo就足够了,不需要Write-Output "$foo"

To put it all together:把它们放在一起:

# 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
  }
}

Note:笔记:

  • I've removed unnecessary ;我删除了不必要的; and I've switched to using verbatim (single-quoted) strings ( '...' ) when no string interpolation via expandable (double-quoted) strings ( "..." ) is required, both for conceptual clarity and to avoid potentially unwanted expansions.当不需要通过可扩展(双引号)字符串"..." )进行字符串插值时,我已经切换到使用逐字(单引号)字符串'...' ),这既是为了概念清晰,也是为了避免可能不需要的扩展。

  • Note the use of aux.注意辅助的使用。 variable $thisApp in the App key, which allows referencing it in the later Destination key, in an expandable string ( "c:\Deploy\$thisApp.exe" ). App键中的变量$thisApp ,允许在后面的Destination键中以可扩展字符串 ( "c:\Deploy\$thisApp.exe" ) 引用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM