calling script from command line powershell.exe breaks array

I have a script I found on the internet for swapping out printers when you get a new print server. https://gallery.technet.microsoft.com/scriptcenter/PowerShell-Script-for-057ae37a. I don’t know if my issue is specific to the script. I suspect it isn’t. if I run it in powershell, or the ISE, it works great. but if I call it from a command prompt with powershell.exe, it breaks.

it uses get-wmiobject WMI to collect the current printers. this works great.
as it’s collecting the current printers, it adds them to an array called “$global:printerstobedeleted”
it uses a switch table to replace the current printers with their new print server counterparts. this works great.
after it has added the new printers, it does a foreach through the $global:printerstobedeleted" aray (of old printers), and deletes each one.

my issue is with the array. as I said, if I run this in a powershell window or in the ISE, it works fine. but if I call the script from a command prompt:

   powershell.exe "&\\server\share\script.ps1"

it suddenly has trouble reading the array. specifically, it doesn’t seem to detect the array members as separate objects. it detects all the printer names as one long string.

so if I add a line to the script to output that $global:printerstobedeleted variable, and run the script in powershell, I get this:

 full list of printers to be deleted: \\sisfpsp6\TX095-110PCL \\sisfpsp6\TX095-132PCL

notice a space between the printer names.

if I run the script from a command prompt by calling powershell.exe, I get this:

 full list of printers to be deleted: \\sisfpsp6\TX095-132PCL\\sisfpsp6\TX095-110PC

no space between the printer names. later when the delete function runs its ‘foreach’ against that variable, it runs against that one long string, instead of each separate printer name.

why would calling the script from a command prompt matter? i’m on windows 8.1 with powershell 4.

Took a look at the script and I don’t really understand the logic of collecting all the printers to remove to do it later. Here is the same script highly simplified without the functions, global and other unnecessary items:

# Set print server name 
$Printserver = "." 
 
# This section will identify all the installed Network printer under logged in users profile using WMI 
$Printers = Get-WMIObject Win32_Printer -computername $Printserver -Filter "Network=True" 
 
if($Printers) { 
      # Get Network object 
      $net = new-Object -com WScript.Network 
 
      foreach ($Printer in $Printers){ 
          $newPrinter = "" 
          #Just swap your old printer name with new server\printer name here 
          switch ($Printer.ShareName)  {  
              "SV01Dispatch-M" {$newPrinter = "\\SRV-PSTREET01\SV-01-M7"} 
          } 
          
          if ($newPrinter -ne "") { 
               if ($Printer.Default) {$defaultPrinter = $newPrinter} 
                $net.AddWindowsPrinterConnection($newPrinter)   
                $net.RemovePrinterConnection($Printer.Name)
          } 
      } 
     $net.SetDefaultPrinter($defaultPrinter)
} 

This isn’t tested, but you should get the jest.

Rob, I appreciate it, but unfortunately, that script does not successfully set the new default printer, and does not answer my question about why the original script works fine when called directly from powershell, but won’t delete printers if it’s called from a command prompt with powershell.exe.

Change this line: $PrintersTobeDeleted = @()
to: $global:PrintersTobeDeleted = @()

Now does it work?

Failing that, move the functions so they come after the initialisation of $global:PrintersTobeDeleted = @()

I think the function InstallNewPrinter, when adding $currentPrinter to the PrintersToBeDeleted array is not adding it to the initialised $PrintersTobeDeleted = @() array.

So it’s simply treating $global:PrintersToBeDeleted as an entirely different variable to the initialised $PrintersTobeDeleted = @(), and thus is not acting like an array, but acting like a string. It’s adding a string value (printer name) to itself, so you end up with the issue you’re facing where all names are shoved together in a single string.

that did the trick. thank you. it’s still odd that the original script worked from the ISE, but did not work when calling it from the command prompt.

In Powershell ISE, the script scope is also the global scope. Running in the powershell console or from powershell.exe it is not.

Take this example and run it the three ways:

$a = 'local'
$global:a = 'global'
$script:a = 'script'

"local: $a"
"global: $global:a"
"script: $script:a"

Its so you can inspect and modify the variables in the script in ISE.