3

Need help troubleshooting an the Array and Scriptblock OR Maybe this is better using param and functions???

Script Objective: To easily update the list of applications to be installed

Getting error below.

' At 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. + 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
1
  • I would recommend creating a parameterized function for this kind of work. Commented Mar 10, 2022 at 16:32

1 Answer 1

4

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

  • There's no need to use a separate script block ({ ... }) - just use the body of the foreach loop statement.

    • 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 (e.g. $sb = { 'hi' }; & $sb). Invoke-Command's primary purpose is to execute a script block on a remote machine.
  • Generally, you can use variables as-is as command arguments, without enclosing them in "..." - even if their values contain spaces. E.g., Write-Output $foo is sufficient, no need for 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").

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.