So I am trying to add printers using PowerShell. Before this, I did look into using GPOs to deploy printers, but I kept getting an errors. My predecessor created a VBS script to deploy them, but I am in the process of converting them all to PowerShell. Now at first I used the Add-Printer cmdlet with the -ConnectionName parameter. This worked at first, but after multiple tries, I kept getting errors that said the printer is not accessible. Then I thought about going to COM objects, and this works perfectly. However I am running into one snag. If the printers are already added, they just go away, and then I get an error saying "Value does not fall within the expected range."

The script is called via a GPO logon. The reason I am deploying them in this fashion is that all users profiles are purged (using WMI objects) and each logon session should be new for the user. Also, they do not have administrative privileges. However, they do have access to the print server, and they do have the ability to add printers. I know this because I can manually run the script in the user's context and it runs just fine. I can also see the printers being added, if they are not already there. It's just if the user logs out, and then logs back in, the printers are there, but then they disappear one by one, even though the profile is being created the first time each time. So I thought I could possibly remove all printers (except for the Microsoft PDF) printer, but that doesn't seem to work either.

Here is the code I am using. Obviously the names have been changed, but in the real script, the names are just fine. I am also using FQDN in the true script as well.

Start-Transcript -Path C:\Temp\PowerShellLog.txt

$printers = Get-Printer
Get-Printer | Where-Object Name -NotLike "*PDF*" | Remove-Printer

$var = New-Object -COM WScript.Network 
Start-Sleep -Seconds 5
if ($printers.name -notcontains "\\printerserver.company.com\LAB A P1") { $var.AddWindowsPrinterConnection("\\printerserver.company.com\LAB A P1") }
Start-Sleep -Seconds 5
if ($printers.name -notcontains "\\printerserver.company.com\LAB A P2") { $var.AddWindowsPrinterConnection("\\printerserver.company.com\LAB A P2") }
Start-Sleep -Seconds 5
if ($printers.name -notcontains "\\printerserver.company.com\LAB A Duplex") { $var.AddWindowsPrinterConnection("\\printerserver.company.com\LAB A Duplex") }
Start-Sleep -Seconds 5
if ($printers.name -notcontains "\\printerserver.company.com\LAB A Color") { $var.AddWindowsPrinterConnection("\\printerserver.company.com\LAB A Color") }

#Makes default printer
$var.setdefaultprinter("\\printerserver.company.com\LAB A P1")

Here is the error I get if the printer is already installed (but then goes away):

 Value does not fall within the expected range. At
\\server\Hidden$\printer.ps1:12 char:87
+ ...  Duplex") { $var.AddWindowsPrinterConnection("\\printerserver ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + CategoryInfo          : OperationStopped: (:) [], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException
  • @PimpJuiceIT Thanks for the comments. So first all, we have AllSigned turned on. The script is signed, and it runs manually. The script itself runs because the Start-Transcript is processing the .txt file. So I believe we can eliminate that. This needs to be in the user's context, and not the system, because the users do not have admin rights. Like I said, I ran the script manually, and the printers do add. It is when the printers are already there, they start to disappear, and that's when I get the error. – Herc08 Feb 12 at 12:47
  • I do that was well. I even copied the script locally to make sure there was no issue there. But everything I am doing, I am doing as a standard user, not with any administrative access. Start-Transcript pretty much just copies the contents of the console window to the text file, which is how I know what error I am getting. – Herc08 Feb 12 at 14:11
  • 1
    That's not in the error, that's just SuperUser's formatting messing up the slashes. However, someone gave me an idea to work with WMI objects, and figured out the issue. I will post my answer shortly. Thanks for your time. – Herc08 Feb 12 at 14:38

So after doing research for the past 3 hours I figured out what the issue could possibly be. At startup, we clean up all user profiles. This requires administrative access, so it is down at the system level. Since the printers are being added in the user context, the profile cleanup doesn't clean up the printers as well. I figure there is some conflict, and the printers are caught in limbo. So if I go to add the same printer with the same network path, that is way it disappears.

With that said, I have a logoff script to empty the Recycle Bin, as this is also in the user's space. Right under that, I added Get-WmiObject -Class Win32_Printer | Where-Object { $_.Network -eq 'true' } | ForEach-Object { $_.delete() } which should clean up the network printers during logoff. As far as the script goes, COM objects would work, but figured using WMI objects would be just as effective. Here is the script to add the printers at logon. I hope this helps someone else in the future.

$printclass = [wmiclass]"win32_printer"
$printclass.AddPrinterConnection("\\printerserver.company.com\LAB A P1")
$printclass.AddPrinterConnection("\\printerserver.company.com\LAB A P2")
$printclass.AddPrinterConnection("\\printerserver.company.com\LAB A Color")
$printclass.AddPrinterConnection("\\printerserver.company.com\LAB A Duplex")

#Makes default printer
$P1Printer = Get-WmiObject -Class Win32_Printer | Where-Object { $_.Network -eq 'true' -and $_.Name -like "*LAB A P1*" }
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.