Mismatched Brackets in script

I had this script working, then someone shutdown their computer while I was installing Sophos. I saved the script, and rebooted my computer. When I started up again, it appears that I have mis-matched brackets or something that makes it appear the brackets do not match. I’m embarrassed to bring this to the forum, but I have spent at least 3 days staring at the code and not seeing the problem. I even had a friend with a lot of PowerShell experience look it over, but he couldn’t locate the problem.

Here is the code:

  $csv = Import-Csv "C:\Users\michaelk\Downloads\staffcomputers.txt"
  $Items = New-Object System.Collections.Generic.List[System.Object]
  $FailedInstalls = New-Object System.Collections.Generic.List[System.Object]
  $cred = Get-Credential hfkschool.org\michaelk
  #reads .csv for workstation NAME.
 
  #reads .csv for workstation NAME.
  foreach ($line in $csv)
  {
#     Write-Host "$line"
      #pings each Host. If true, Copy file.
      if (Test-Connection $line -count 1 -quiet)
      {
#          write-Host "true", $line
		   $InstallName =  "\\" + $line + "\C$\Sophos"
#		   $name = "C\Sophos\SophosInstall.bat"
		   #Remove Dell proteched Space
		   #$ErrorActionPreference = "silentlyContinue"
		   $app = Get-WmiObject -Class win32_product -Filter name = "Dell Protected WorkSpace"
		   $result = $app.uninstall()		  
		   #Installs the Sophos on the target computer
		   If (Test-Path -path ("\\" + $line + "\C$\Sophos"))
		   {   
				Write-Host "Dir Found"
				Remove-Item ("\\" + $line + "\C$\Sophos") -recurse
		   }
		   new-Item -Path $InstallName -ItemType Directory -Force 
		   write-host "Copying files"
		   Copy-Item -path "C:\Sophos\*.*" -Force -Destination $InstallName
		   Write-Host $line
	  	   Invoke-Command -ComputerName $line -Credential $cred  -ScriptBlock {Start-Process  -Wait -FilePath "c:\sophos\SophosSetup.exe" -argument "--quiet" -WorkingDirectory "c:\Sophos\"}
	   }
      else
      {
          #if ping fails, log which workstation and that workstation's IP in a new CSV.
		  $Items.add($line)
      }
  }
$error[0] 
#  Write-Host $items
  #exports array of workstations that were unreachable for manual processing at a later date.
  $items | add-content -path C:\Sophos\missingworkstations.txt

Well I don’t know what happened to the formatting, sorry.

Someone messed it up. :wink:

But that’s not a problem. You can go back, edit your existing post and fix the formatting. Without that it will be nearly impossible for us to help you further, sorry.

Regardless of that - I urgently recommend for you to use VSCode to write your PowerShell code. It will support you with showing the bracket pairs and you can even install some extensions like indent rainbow to increase the visibilty of the according brackets, parenthesis and so on.

(post deleted by author)

Please DO NOT CREATE NEW POSTS. You can edit your existing ones!!!

When you post code or sample data or console output please format it as code using the preformatted text button ( </> ). Simply place your cursor on an empty line, click the button and paste your code.
Thanks in advance

Can you tell me how to delete a post? I made hamburger out of this one.

There’s no need to. Simply delete your second post and fix the first one. Click on the 3 dots below the post. There you can access your options.

Olaf thanks for helping me out. Can you tell me how to get Powershell scripts to post properly.

I already did!! Please read my answers.

As far as I can see there is no bracket rhythm error. Why do you think you have such an error? Do you get an error message running the script? If yes you should post this error here completely formatted as code please.

Regardless of that I’d recommend to use Invoke-Command to run all commands remotely instead of using the UNC path. Not just the installation of Sophos. It’ll speed up your script and make it easier to read and easier to maintain.

The reason I think there is a problem is that if I run the script in a console after the foreach statement the prompt turns into “>>” runs to the end of the script and the script never finishes. I have to abort it. I couldn’t think of anything that could cause this behavior besides mismatched brackets. I have gone over the brackets and the quotes with a fine tooth comb, but I cannot find the problem. Here is the output from running it from the console.

PS C:\Users\michaelk>   $csv = Import-Csv "C:\Users\michaelk\Downloads\staffcomputers.txt"
PS C:\Users\michaelk>   $Items = New-Object System.Collections.Generic.List[System.Object]
PS C:\Users\michaelk>   $FailedInstalls = New-Object System.Collections.Generic.List[System.Object]
PS C:\Users\michaelk>   $cred = Get-Credential hfkschool.org\michaelk
PS C:\Users\michaelk>   #reads .csv for workstation NAME.
PS C:\Users\michaelk>
PS C:\Users\michaelk>   #reads .csv for workstation NAME.
PS C:\Users\michaelk>   foreach ($line in $csv)
>>   {
>> #     Write-Host "$line"
>>       #pings each Host. If true, Copy file.
>>       if (Test-Connection $line -count 1 -quiet)
>>       {
>> #          write-Host "true", $line
>>            $InstallName =  "\\" + $line + "\C$\Sophos"
>> #           $name = "C\Sophos\SophosInstall.bat"
>>            #Remove Dell proteched Space
>>            #$ErrorActionPreference = "silentlyContinue"
>>            $app = Get-WmiObject -Class win32_product -Filter name = "Dell Protected WorkSpace"
>>            $result = $app.uninstall()
>>            #Installs the Sophos on the target computer
>>            If (Test-Path -path ("\\" + $line + "\C$\Sophos"))
>>            {
>>                 Write-Host "Dir Found"
>>                 Remove-Item ("\\" + $line + "\C$\Sophos") -recurse
>>            }
>>            new-Item -Path $InstallName -ItemType Directory -Force
>>            write-host "Copying files"
>>            Copy-Item -path "C:\Sophos\*.*" -Force -Destination $InstallName
>>            Write-Host $line
>>              Invoke-Command -ComputerName $line.Name -Credential $cred  -ScriptBlock {Start-Process  -Wait -FilePath "c:\sophos\SophosSetup.exe" -argument "--quiet" -WorkingDirectory "c:\Sophos\"}
>>        }
>>       else
>>       {
>>           #if ping fails, log which workstation and that workstation's IP in a new CSV.
>>           $Items.add($line.Name)
>>       }
>>   }
>> $error[0]
>> #  Write-Host $items
>>   #exports array of workstations that were unreachable for manual processing at a later date.
>>   $items | add-content -path C:\Sophos\missingworkstations.txt
>>
PS C:\Users\michaelk> $csv = Import-Csv "C:\Users\michaelk\Downloads\staffcomputers.txt"
PS C:\Users\michaelk>   $Items = New-Object System.Collections.Generic.List[System.Object]
PS C:\Users\michaelk>   $FailedInstalls = New-Object System.Collections.Generic.List[System.Object]
PS C:\Users\michaelk>   $cred = Get-Credential hfkschool.org\michaelk
PS C:\Users\michaelk>   #reads .csv for workstation NAME.
PS C:\Users\michaelk>
PS C:\Users\michaelk>   #reads .csv for workstation NAME.
PS C:\Users\michaelk>   foreach ($line in $csv)
>>   {
>> #     Write-Host "$line"
>>       #pings each Host. If true, Copy file.
>>       if (Test-Connection $line -count 1 -quiet)
>>       {
>> #          write-Host "true", $line
>>            $InstallName =  "\\" + $line + "\C$\Sophos"
>> #           $name = "C\Sophos\SophosInstall.bat"
>>            #Remove Dell proteched Space
>>            #$ErrorActionPreference = "silentlyContinue"
>>            $app = Get-WmiObject -Class win32_product -Filter name = "Dell Protected WorkSpace"
>>            $result = $app.uninstall()
>>            #Installs the Sophos on the target computer
>>            If (Test-Path -path ("\\" + $line + "\C$\Sophos"))
>>            {
>>                 Write-Host "Dir Found"
>>                 Remove-Item ("\\" + $line + "\C$\Sophos") -recurse
>>            }
>>            new-Item -Path $InstallName -ItemType Directory -Force
>>            write-host "Copying files"
>>            Copy-Item -path "C:\Sophos\*.*" -Force -Destination $InstallName
>>            Write-Host $line
>>              Invoke-Command -ComputerName $line -Credential $cred  -ScriptBlock {Start-Process  -Wait -FilePath "c:\sophos\SophosSetup.exe" -argument "--quiet" -WorkingDirectory "c:\Sophos\"}
>>        }
>>       else
>>       {
>>           #if ping fails, log which workstation and that workstation's IP in a new CSV.
>>           $Items.add($line)
>>       }
>>   }
>> $error[0]
>> #  Write-Host $items
>>   #exports array of workstations that were unreachable for manual processing at a later date.
>>   $items | add-content -path C:\Sophos\missingworkstations.txt

You’re not running the script. You’re dropping the code into a console window. :wink:

I’d recommend to use this occasion as a chance to rewrite/refactor your script. Start with one step at a time and add the next step if the last one is working as expected.

I’d start with renaming the input file extension to CSV and dropping the unnecessary outputs to the console. If you want to have verbose output or debug output you should use

or

This way you can switch on the output when you need but it will not bother when the script runs in a production environment.
This may be a starting point:

$ComputerNameList = Import-Csv -Path 'C:\Users\michaelk\Downloads\staffcomputers.CSV'
$Credential = Get-Credential -UserName 'hfkschool.org\michaelk'

foreach ($ComputerName in $ComputerNameList) {
    if (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet) {
        Invoke-Command -ComputerName $ComputerName -Credential $Credential -ScriptBlock {
            if (Get-CimInstance -ClassName win32_product -Filter "Name = 'Dell Protected WorkSpace'") {
                Write-Debug "Installation of 'Dell Protected WorkSpace' exists on Computer '$($ComputerName)'"
            }
            If (Test-Path -path 'C:\Sophos') {   
                Write-Debug "Path 'C:\Sophos' exists on Computer '$($ComputerName)'"
                Remove-Item 'C:\Sophos' -Recurse -Force
            }
        }
    }
}

Before you run this code you set

$DebugPreference = 'Continue'

This way you see the debug output and when you’re done you simply go back to

$DebugPreference = 'SilentlyContinue'

And you don’t have to change your script but you get rid of the now unnecessary debug output.

I would start testing with one or two TEST computers first. And move forward when you’re satisfied with the code.

Thank you for all of your suggestions. I’ve been trimming the script down and using variable names that makes more sense. I’m going to take your suggestion and build a new script one step at a time.

1 Like

Final post on this subject. I took the script apart and then put in back together piece by piece. Along the way I found a “]” on a blank line that was way off the page to right. That seemed to be causing he problem and I’m back up and running. Thanks again for the help.