Adding Printer via Powershell Script

Hi there,

New to the forum. I would like to see if anyone else have came across this issue that I am experiencing where running the code below:

[pre]

$i = “\server\printer-shared-name”

$net = New-Object -COM WScript.Network

$net.AddWindowsPrinterConnection($i)

[/pre]

But i received this error message:

Value does not fall within the expected range.
:
At somelocation\powershell.ps1:94 char:13

  • $net.AddWindowsPrinterConnection($i)
  • CategoryInfo : OperationStopped: (:slight_smile: , ArgumentException
  • FullyQualifiedErrorId : System.ArgumentException

However, have the script retry running $net.AddWindowsPrinterConnection($i) again and sometimes it works and sometimes it fails with the same message.

Weird indeed. Anyone happen to have seen this issue before?

In addition, I have this powershell script run on login.

Different users login with their domain account and something it works perfectly and sometimes it doesn’t and return this error.

 

Do you regularly delete profiles?

Does the print server accept random high ports in its firewall?

[quote quote=158606]Do you regularly delete profiles?

Does the print server accept random high ports in its firewall?

[/quote]

Thanks for your reply. We do not delete profiles from the Windows 10 computer.

Possibly can you share with me how the mechanism works regarding high ports in its firewall or what relation it has to do with high ports.

 

Thank you

These are two things it took me many weeks to figure out after moving to windows shared printers:

The server print spooler service listens on a high random port (rcp). This is open by default unless you have a 3rd party firewall in between. This can cause like a 45 second delay when adding printers after a reboot or the spooler service on the client is restarted. It can also reduce performance. If there’s a link that explains this, I could never find it.

Another problematic feature added since windows server 2008 is the “Client Side Rendering Print Provider” or “CSR” in the logs. It sort of turns every client into a server. It adds a lot of registry entries that can put the computer into an unpredictable state if profiles are deleted. You may see things like printers not being added or printers you don’t want anymore being added when a user with the same sid recreates his profile. It seems better to disable Client Side Rendering in group policy.

This isn’t an answer to your question, but I’m curious why you’re using COM objects instead of the native cmdlets for printers (Get-Command print). Granted the more useful cmdlets are only available in PS 5, but they should be able to handle a printer install. If you’re working with Windows 7 machines that only have powershell 2.0, you would most likely need to fall back on the built in printer admin vb files.

Note that even powershell add-printer calls wmi.

Although the problem is not resolved yet but I appreciate everyone’s feedback.

I’ve added a retry while loop to my script with 10 seconds delay (Start-Sleep -s 10) between each try that calls the AddWindowsPrinterConnection()

It seems to have better success rate in adding the printer on the second try.

 

At the same time, the reason why we are using COM objects is because of mixed operating systems in our environment such as window 7 and 10… and yes, the powershell on the windows 7 computers is an older version that doesn’t support Add-printer / Remove-printer cmdlets.

 

If anyone has any idea to share, feel free to reply back to this thread.

If you’re desperate, try this script on a test machine. If domain user profiles are occasionally deleted, their sid’s don’t get deleted from this area. It causes all kinds of chaos when the same domain user with the same sid logs back in. This would only happen in windows 8 and above.

mkdir c:\tools
copy c:\users\admin\desktop\psexec.exe c:\tools
# clean up network printers
Get-Service *spool* | Stop-Service
# must be the system user to delete these
& c:\tools\PsExec.exe -accepteula -s -i reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\SWD\PRINTENUM" /f
& c:\tools\PsExec.exe -accepteula -s -i reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\{0ecef634-6ef0-472a-8085-5ad023ecbccd}" /f                                                              
& c:\tools\PsExec.exe -accepteula -s -i reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Providers\Client Side Rendering Print Provider" /f
Get-Service *spool* | Start-Service

If all else fails, you can fall back on the built in printer admin script (C:\Windows\System32\Printing_Admin_Scripts\en-US). They’re available in both Win 7 and 10, and are fairly well documented. They are a bit old and clunky to work with though.

I don’t have a printer to test this with, but this might also help out.

function Install-Printer {
    param (
        [string]$PrinterShare = "\\server\printer-shared-name"
    )
$OS = Get-WmiObject win32_operatingsystem -ComputerName $ENV:COMPUTERNAME

if ($OS.caption -like "*Windows 10*") {
    Add-Printer -ConnectionName $PrinterShare
}

if ($OS.caption -like "*Windows 7*") {
    Set-Location -Path "C:\Windows\System32\Printing_Admin_Scripts\en-US\"
    Invoke-Command -ScriptBlock {cscript.exe prnmngr.vbs -ac -p "$PrinterShare"}
}

}