question

Precision-2034 avatar image
0 Votes"
Precision-2034 asked Precision-2034 edited

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

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
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

When you post code, please use the Code Sample editor. It's the one with the "101 010" icon on the formatting bar. Or use "Ctrl+K" to activate the editor.

Posting code as if it were text not only makes it difficult to understand, it may also screw up the contents of your code!

Please edit your post and replace the code portion using the Code Sample editor.

If you use a competent code editor for your development and debugging you'll find that common mistakes like mismatched parentheses, brackets, and quotes are easily discovered. Try either VS Code or Visual Studio.


0 Votes 0 ·
Precision-2034 avatar image Precision-2034 RichMatheisen-8856 ·

Thank you for the information I have updated my post, any assistance in fixing the code is appreciated, thank you.

0 Votes 0 ·
Precision-2034 avatar image Precision-2034 RichMatheisen-8856 ·

I'm still lost on how to resolve the error, can anyone help please.

0 Votes 0 ·
RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered MotoX80 commented

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}
     }
 }
· 8
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I'm sorry I don't script powershell. I found this online and have been trying to figure out why it's not working. The changes you suggested I'm not sure where to begin. Is it possible to just help me correct that section so that the script will run?

0 Votes 0 ·

Sure. Read the 1st line of my previous answer.

0 Votes 0 ·

If I add the { I receive the following error



 At line:119 char:173
 + ...  ($value.startswith($AdobeFlash)) -or ($value.startswith($Firefox)) {
 +                                                                         ~
 Unexpected token '{' in expression or statement.
 At line:119 char:173
 + ...  ($value.startswith($AdobeFlash)) -or ($value.startswith($Firefox)) {
 +                                                                         ~
 Missing closing ')' after expression in 'if' statement.
 At line:103 char:5
 +     {
 +     ~
 Missing closing '}' in statement block or type definition.
 At line:81 char:1
 + {
 + ~
 Missing closing '}' in statement block or type definition.
     + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
     + FullyQualifiedErrorId : UnexpectedToken


0 Votes 0 ·

Sorry . . . you're also missing the closing right-parenthesis. Replace the "{" with "){"

0 Votes 0 ·
Precision-2034 avatar image Precision-2034 RichMatheisen-8856 ·

I commented out a couple of lines and got to run, but now I'm getting different errors

 Function : The term 'Function' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a 
 path was included, verify that the path is correct and try again.
 At line:81 char:1
 + Function queryComputer($SystemName)
 + ~~~~~~~~
     + CategoryInfo          : ObjectNotFound: (Function:String) [], CommandNotFoundException
     + FullyQualifiedErrorId : CommandNotFoundException


0 Votes 0 ·
Show more comments
RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered

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
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.