powershell error with missing closing')' after expression in 'if' statement

Precision 1 Reputation point
2021-09-23T05:05:53.58+00:00

Hello, I am new to PowerShell and am trying to use the script below however I am getting a couple errors, could someone please help me fix them, thank you.

At line:121 char:1

  • $DisplayVersion = $ReadUninstall.GetValue("DisplayVersion")

Missing closing ')' after expression in 'if' statement. At line:154 char:1

  • }
  • ~ Unexpected token '}' in expression or statement.
    • CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
    • FullyQualifiedErrorId : MissingEndParenthesisAfterStatement
    $SystemList = Get-content ".\System_List.txt" $PrintResultsToCSV = @() ########### $windowsupdate = {...} Function queryComputer($SYstemName) {...} foreach ($SystemName in $SystemList) {...} foreach ($SystemName in $SystemList) {...} $PrintResultsToCSV | export-csv .\GSECGOLDRecults.csv =Notypeinformation foreach ($SystemName in $SystemList) { Write-host$SystemName ping -n 1 $SystemName |Out-Null
      if ($? -eq $false) {
          "System Not Reachable"
          return
      }
    
    $ReturnFunction = queryComputer $SystemName $obj = Get-WmiObject Win32_operatingSystem -ComputerName $SystemName $restartPssession = $false $regservPSSession = Get-WmiObject -ComputerName $SystemName -Class Win32_Service -Filter "Name = 'WinRm'" if ($regservPSSession.State -eq "Stopped") { $regservPSSession.startservice() | Out-Null $restartPSSession = $true } $Remotesession = new-PSSession -ComputerName $SystemName $RemoteReturnResult = Invoke-Command -Session $Remotesession -Scriptblock $windowsupdate | Select @{Label = "System Name"; Expression = {$Systemname}}, @{LABEL='Operating System' ;EXPRESSION={$obj.Caption}}, @{LABEL='Missing Patches' ;EXPRESSION={$_}}, @{LABEL= 'Last Boot Time' ;EXPRESSION={$obj.ConvertToDateTime($obj.LastBootUpTime)}}, @{LABEL='Chrome version';EXPRESSION={ReturnFUnction.Chrome}}, @{LABEL='Firefox Version';EXPRESSION={ReturnFunction.Firefox}}, @{LABEL='Java Verstion' ;EXPRESSION={ReturnFunction.Java}}, @{LABEL='Adobe Flash Version' ;EXPRESSION={$ReturnFunction.FLash}}, @{LABEL='Adobe Reader Version';EXPRESSION={ReturnFunction.Reader}}; PrintResultsToCSV += $RemoteReturnResult Remove-PSSession $Remotesession if ($restartPssession -eq $true) { $regservPSSession.StopService() | Out-Null } } $windowsupdate = { $UpdateSession = New-object -ComObject microsoft.update.session $UpdateSearcher = $UpdateSession.CreateUpdateSearcher() $SeachResult = $UpdateSearcher.Search("IsAssigned=1 and IsHidden=0 and IsInstalled=0") write-Host "total=$($SeachResult.updates.count)" Write-Output $SearchResult.updates.count } $obj = Get-WmiObject Win32_OperatingSystem -computername $SystemName @{LABEL='OperatingSystem';EXPRESSION={$obj.Caption}} @{LABEL='Last Boot Time';EXPERSSION={$obj.ConvertToDateTime($obj.LastBootUpTime)}}| Function queryComputer($SystemName) { $ReturnfromFunction = @{} $Branch="LocalMachine" $SubBranch="SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" $restartReg = $false $regserv = Get-WmiObject -ComputerName $SystemName -Class Win32_Service -Filter "Name ='RemoteRegistry'" if ($regserv.State -eq "Stopped") { $regserv.StartService() | Out-Null $restartReg = $true }
      try {
          $registry=[microsoft.win32.registrykey]::OpenRemoteBaseKey($Branch,$SystemName)
      } catch {
          return
      }
    
      $registrykey=$registry.OpenSubkey($Subbranch)
      $SubKeys=$registrykey.GetSubKeyNames()
    
      Foreach ($key in $subkeys)
      {
    
          $exactkey=$key
          $NewSubkey=$SubBranch+"\\"+$exactkey
          $ReadUninstall=$registry.OpenSubKey($NewSubKey)
          $value=$ReadUninstall.GetValue("DisplayName")
    
    #|
          if (($Value -ne "") -and ($value -ne $null)) {
                          $chrome = "Google Chrome"
                          $Firefox = "Mozilla Firefox"
                          $Java = "Java"
                          $AdobeReader = "Adobe Acrobat Reader"
                          $AdobeFlash = "Adobe Flash"
    
    if(($value.startswith($chrome)) -or ($value.startswith($java)) -or ($value.startswith($AdobeReader)) -or ($value.startswith($AdobeFlash)) -or ($value.startswith($Firefox)) $DisplayVersion = $ReadUninstall.GetValue("DisplayVersion")
                      if ($value.startswith($chrome)){$chromeVersion = ($DisplayVersion)
                                      }else{$chromeVersion = "Not Installed"}
    
                      if ($value.startswith($java)){$JavaVersion = ($DisplayVersion)
                                      }else{$JavaVersion = "Not Installed"}
    
                      if ($value.startswith($AdobeReader)){ReaderVersion = ($DisplayVersion)
                                      }else{$ReaderVersion = "Not Installed"}
    
                      if ($value.startswith($AdobeFlash)){FlashVersion = ($DisplayVersion)
                                      }else{$FlashVersion = "Not Installed"}
    
                      if ($value.startswith($FirefoxVersion)){$FirefoxVersion = ($DisplayVersion)
                                      }else{$FirefoxVersion = "Not Installed"}
    
    } } }
      if ($restartReg -eq $true) {
          $regserv.StopService() | out-null
      }
    
    $ReturnfromFunction.Chrome = $chromeVersion $ReturnfromFunction.java = $JavaVersion $ReturnfromFunction.Reader =$ReaderVersion $ReturnfromFunction.Flash = $FlashVersion $ReturnfromFunction.Firefox = $FirefoxVersion return $ReturnFromFunction } $PrintResultsToCSV | export-csv .\GSECGOLDResults.csv -Notypeinformation
Windows Server PowerShell
Windows Server PowerShell
Windows Server: A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.PowerShell: A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
5,389 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Rich Matheisen 45,096 Reputation points
    2021-09-23T18:34:39.13+00:00

    You're missing the opening "{" after the "IF" on line 119.

    I think you can rewrite that whole "IF" more concisely, though:

    if (($Value -ne "") -and ($null -ne $value)) {
        $chromeVersion = "Not Installed"
        $JavaVersion = "Not Installed"
        $ReaderVersion = "Not Installed"
        $FlashVersion = "Not Installed"
        $FirefoxVersion = "Not Installed"
    
        Switch -Wildcard ($value) {
            "Google Chrome*         {$chromeVersion  = $ReadUninstall.GetValue("DisplayVersion"); break}
            "Java*                  {$JavaVersion    = $ReadUninstall.GetValue("DisplayVersion"); break}
            "Adobe Acrobat Reader*" {$ReaderVersion  = $ReadUninstall.GetValue("DisplayVersion"); break}
            "Adobe Flash*"          {$FlashVersion   = $ReadUninstall.GetValue("DisplayVersion"); break}
            "Mozilla Firefox*"      {$FirefoxVersion = $ReadUninstall.GetValue("DisplayVersion"); break}
        }
    }
    

  2. Rich Matheisen 45,096 Reputation points
    2021-10-06T02:32:36.807+00:00

    Well, I gotta say, the way that script is presented in the PDF is awful. Who publishes scripts using screenshots? And who butchers the code by slicing the script into pieces (each a portion of the whole script). Once you get over that and actually assemble the pieces, you have to fix mistakes in the code (not many, but they're there). And the code itself is in a style that looks to be an adaptation from Visual Basic. And there's way too much code and intermediate variable use, and the indentation is inconsistent. It also uses a PSSession (unnecessarily) after making sure that WinRM is running on the remote machine! Oh, and did I mention that there are Wa-a-a-y to many comments? It's a very cluttered bit of work.

    I straightened out most of it, removed a number of unnecessary variables, and used pipelining in the main body of the code.

    I only have one machine so I can't verify that it works, but it's easier to read and has no syntax errors, missing parentheses, or missing braces. See if this version at least runs without errors. Just change the first two lines to agree with the location of the two files:

    $SystemNames = 'c:\junk\SystemNames.txt'
    $OutputCSV =   'c:\Junk\GSECGOLDResults.csv'
    
    # Declares values and defines the strings of program names that are being searched for
    $chrome = "Google Chrome"
    $firefox = "Mozilla Firefox"
    $java = "Java"
    $adobereader = "Adobe Acrobat Reader"
    $adobeflash = "Adobe Flash"
    
    # create a SCRIPT-BLOCK to be run on the remote systems
    # Check for windows updates on the remote PSSession - This is a remote session so value $Searchresult is transferred back to the main script with the write-output command
    $windowsupdate =
    {
        # below does a search for Critical and Important updates that have not been installed
        $UpdateSession = New-Object -ComObject Microsoft.Update.Session
        $UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
        $SearchResult = $UpdateSearcher.Search("IsAssigned=1 and Hidden=0 and IsInstalled=0")
        # Below writes the amount of Important and Critical patches missing on the remote system to the screen
        Write-Host "total=$(SearchResult.updates.count)"
        # Below exports the results (total number of patches missing) to the $windows update variable in the main script
        Write-Output $SearchResult.updates.count
    }
    ########### End of windows update on remote session
    
    ###########
    Function queryComputer($SYstemName)
    {
        # creation of the HASH $returnformfunction
        $ReturnfromFunction = [ordered]@{
            'Chrome'  = "Not Installed"
            'Firefox' = "Not Installed"
            'Java'    = "Not Installed"
            'Reader'  = "Not Installed"
            'Flash'   = "Not Installed"
        }
    
        $Branch = "LocalMachine"    # Branch of the registry HKEY for local machine
        # Main sub branch of the registry you need to open
        $SubBranch = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"  # 32-bit version
        #$SubBranch = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"              # 64-bit version
    
        $restartreg = $false    # sets value of remote registry status to $false - when set to $true it means that this WMI call found remote registry on remote system was off
        # check if the remote registry service is stopped. if so, start it
        $regserv = Get-WmiObject -ComputerName $SystemName -Class Win32_Service -Filter "Name='RemoteRegistry"
        if ($regserv.State -eq 'Stopped'){
            $regserv.StartService() | Out-Null
            $restartreg = $true
        }
        # Attempt to open the HKLM branch. Return from the current query if it fails
        Try{
            $registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($Branch,$SystemName)
        }
        Catch{
            return
        }
        # Get the names of each installed program
        $registrykey = $registry.OpenSubKey($SubBranch)
        $SubKeys = $registrykey.GetSubKeyNames
        # get the display name for each installed program
        ForEach ($key in $SubKeys)
        {
            # the below lines will drill down to the uninstall directory in the registry to grab all the program display names that are installed
            $exactkey = $key
            $NewSubKey = $SubBranch+"\\"+$exactkey
            $ReadUninstall = $registry.OpenSubKey($NewSubKey)
            $value = $ReadUninstall.GetValue("DisplayName")
            # for each value which is not blank
            if ($null -ne $value -and $value -ne ""){
                # The below if statement looks through the values discovered above in the uninstall Registry location and only for the programs defined in the variables above
                $DisplayVersion = $ReadUninstall.GetValue("DisplayVersion") # Declares the value that is holding the display version of each application
                if ($value.startswith($chrome)){
                    $ReturnfromFunction.Chrome = $DisplayVersion
                }
                elseif ($value.startswith($firefox)){
                    $ReturnfromFunction.Firefox = $DisplayVersion
                }
                elseif ($value.startswith($java)){
                    $ReturnfromFunction.java = $DisplayVersion
                }
                elseif ($value.startswith($adobereader)){
                    $ReturnfromFunction.Reader = $DisplayVersion
                }
                elseif ($value.startswith($adobeflash)){
                    $ReturnfromFunction.Flash = $DisplayVersion
                }
            }
        }
        if ($restartReg -eq $true) {
            $regserv.StopService() | out-null
        }
        return $ReturnFromFunction
    }
    
    # Begin main program code
    Get-Content $SystemNames |
        ForEach-Object {
            # This line prints to the command screen below to show what system the script is running against as the script proceeds
            Write-Host $_
            ping -n 1 $_ | Out-Null   # Sends ping echo reauest one time to see if the system is alive
            if ($? -eq $false){
                Write-Host "$_ : System not reachable"  # Prints to screen "System not reachable" if no ping results are returned
            }
            else {
                # Registry check for Specific Applications Versions installed (Firefox, Adobe Reader, Adobe Flash, Java)
                ###################################
                ###################################
                $ReturnFunction = queryComputer $_
                ###################################
                ###################################
                # Declaring the value for the WMI call that will pull the system OS and last boot time
                $obj = Get-WmiObject Win32_OperatingSystem -ComputerName $_
                # Below statement makes a WMI call to remote eystem to see if the WinRM service is running and if it isn't running it starts the service so the PSSession can be run
                $restartPSSession = $false
                $regservPSSession = Get-WmiObject -ComputerName $_ -Class Win32_Service -Filter "Name='WinRM'"
                if ($regservPSSession.State -eq "Stopped"){
                    $regservPSSession.StartService() | Out-Null
                    $restartPSSession = $true
                }
    
                # WHY is a PSSession being used at all? Invoke-Command works without it!
                # If there are additional data needed to connect to the remote machine (different protocol, specific credentials, etc.) Then create a CIMSession and use Get-CIMInstance
                # instead of Invoke-Command!
                # Declaring value for the PSSession that will be called to pull total number of missing patches
                $Remotesession = New-PSSession -ComputerName $_
                # This is the calling of the PSSession windowsUpdate on lines 13-21 in this script. Then the results from the PSSession and WMICall (to gather OS and LastBootTime) and (->Next 1
                # the RemoteRegistry call are all stored in the variabe $RemoteReturnedResult in a printable format, for each system scanned, to be later exported to csv
                $RemoteReturnResult= Invoke-Command -Session $Remotesession -ScriptBlock $windowsupdate |
                                        Select-Object   @{n="System Name";v={$_}},
                                                        @{n="Last Boot Time";v={$obj.ConverTiDateTime($obj.LastBootUpTime)}},
                                                        @{n="Operating System";v={$obj.Caption}},
                                                        @{n="Missing Patches";v={$_}},
                                                        @{n="Chrome Version";v={$ReturnFunction.Chrome}},
                                                        @{n="Firefox Version";v={$ReturnFunction.Firefox}},
                                                        @{n="Java Version";v={$ReturnFunction.Java}},
                                                        @{n="Adobe Flash Version";v={$ReturnFunction.Flash}},
                                                        @{n="Adobe Reader Version";v={$ReturnFunction.Reader}}
                # this closes the open PSSession for each system in the loop
                Remove-PSSession $Remotesession
                # the below command checks to see if the WinRM service was started on the remote system and turns it off if and only if it was turned on earlier in the script
                if ($restartPSSession -eq $true){
                    $regservPSSession.StopService() | Out-Null
                }
                $RemoteReturnResult
            }
        } | Export-Csv $OutputCSV -NoTypeInformation
    
    0 comments No comments