calling script from command line powershell.exe breaks array

This topic contains 5 replies, has 4 voices, and was last updated by Profile photo of Craig Duff Craig Duff 3 months, 1 week ago.

  • Author
    Posts
  • #52424
    Profile photo of John Curtiss
    John Curtiss
    Participant

    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.

    • This topic was modified 3 months, 1 week ago by Profile photo of John Curtiss John Curtiss.
  • #52429
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    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.

  • #52609
    Profile photo of John Curtiss
    John Curtiss
    Participant

    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.

    • #52621
      Profile photo of 84rusty .
      84rusty .
      Participant

      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.

  • #52628
    Profile photo of John Curtiss
    John Curtiss
    Participant

    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.

    • #52646
      Profile photo of Craig Duff
      Craig Duff
      Participant

      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.

      • This reply was modified 3 months, 1 week ago by Profile photo of Craig Duff Craig Duff.
      • This reply was modified 3 months, 1 week ago by Profile photo of Craig Duff Craig Duff.

You must be logged in to reply to this topic.