Bulk-create printer objects on print servers using Windows PowerShell

When installing a new print-server with several hundreds or thousands of printer objects there arentt too much fun doing this manually.

Here are 3 steps to automate this process:

1) Install all the necessary printer drivers on the printserver

2) Create a csv-file with a listing of all printer objects and their properties

3) Bulk-import the printer objects using a script

For the 3rd step Ive created a basic Windows PowerShell script, available on PoshCode.org from this link.

The script contains one function for creating a TCP/IP printer port and one function for creating a printer object. These functions are used in a foreach-loop cycling through the csv-file containing all the printer objects. The script are pretty basic, and should be further expanded with error handling and further details for printer properties.

The script are created and tested on a Windows Server 2008 server against a remote Windows Server 2003 server.
Running the script from Windows Server 2003 returns an access denied error, possibly due to the impersonation-model in Windows Server 2003. However, it should work from Windows Vista, Windows 7, Windows Server 2008 and Windows Server 2008 R2 against remote print-servers (2000/2003/2008/2008 R2).

Especially the ability to set NTFS permissions on the printer objects would be a useful addition in the script.

Please feel free to leave suggestions for improvements in the comments section below.

Update 09.11.2009:
I`ve got some feedback regarding the ability to set NTFS permissions on the printer objects in the script.
A utility called SubInACL from Microsoft could be used for this.

Example usage:
subinacl.exe /printer “\print-serverprinter” /revoke=”Power Users”
subinacl.exe /printer “\print-serverprinter” /grant=”DOMAINDomain Users”

The tool can be downloaded from here.

39 thoughts on “Bulk-create printer objects on print servers using Windows PowerShell

  1. Hi,
    I have this error on try to create print on windows 2008 R2:
    Exception calling “Put” with “0” argument(s): “Generic failure ”
    At C:Usersadministrator.HLUZDesktopcreateprinter.ps1:53 char:12
    + $print.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Any help?

    thanks

  2. Hi! You`re sure the csv-file contains the necessary headers?Printserver,Driver,Portname,Sharename,Location,Comment,Printername.

    The same thing happens if you manually try to run the CreatePrinter function?

  3. Hi,
    The printer port creating work fine, but I have this error on the printer creator. My CSV=
    Printserver,Driver,Portname,IPAddress,Sharename,Location,Comment,Printername
    HL-SPRINTER02,Microsoft XPS Document Writer,10.0.19.1,10.0.19.1,HL-P001,teste,teste,HL-P001

    I have tried configure the printers settings direct on the CreatePrinter funcition, but show me this error:

    PS C:Usersadministrator.HLUZDesktop> .createprinter3.ps1
    Unexpected token ‘.19′ in expression or statement.
    At C:Usersadministrator.HLUZDesktopcreateprinter3.ps1:31 char:26
    + $print.PortName = 10.0.19 <<<< .1
    + CategoryInfo : ParserError: (.19:String) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken

    Thanks for your helping,
    LB

  4. Hi,

    The script work fine but I’m on a Windows 2k8 cluster and when I launch the script it create the printer on the node and not the cluster instance.

    Could you tell me what can I do ?

    Thanks

  5. WMI does not support the cluster virtual machine name, only node names.

    Pick us the Windows Resource Kit and use prnadmin.dll and associated
    scripts and support when scripting printers on the cluster.
    http://www.microsoft.com/downloads/d…DisplayLang=en

    If you have an existing print server, try the print migrator tool if you
    wish to move printers from one or more machines to the cluster.

    http://www.microsoft.com/WindowsServ…grator3.1.mspx

    Source: http://forums.techarena.in/server-cluster/75119.htm

  6. Hi,

    I have the same issue as Leao Braz on a 2008 Server R2 x64. the printer port creation work fine, but I have this error on the printer creator:
    Exception calling “Put” with “0″ argument(s): “Generic failure ”
    At C:tempcreateprinter.ps1:53 char:12
    + $print.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Then i have tried with several drivers and the issue is always the same. I have tried on windows 2003 and it works like a charm…

    Any idea ?

    Help would be appreciated
    Thanks

  7. hi –

    i am having the same issue when trying to create a printer. the below works just fine on XPSP2

    $server = “.”
    $print = ([WMICLASS]”\$serverROOTcimv2:Win32_Printer”).createInstance()

    $print.drivername = “HP Universal Printing PCL 6″
    $print.PortName = “10.1.20.31_PR1″
    $print.Shared = “true”
    $print.Sharename = “ScriptedPrinter2″
    $print.Location = “USA/Redmond/Building 37/Room 115″
    $print.Comment = “HP Universal Printing PCL 6″
    $print.DeviceID = “ScriptedPrinter2″
    $print.Put()

    when i run the same on Win2003 server it fails with the err ” Exception calling Put with 0 arguments: Access Denied” i am totally frustrated now, as i have been trying to research for over 4 days on this. i am using Powerscript 2.0 ver.

    i have tried with various combinations of drivers and port addresses that are added and not used on the server.

    Pls someone help !! what am i missing???

    thanks a lot

  8. Raj: Have you tried running the script against Windows Server 2003 from a remote server/client?

    E.g.:
    $server = “your-win2003-server”
    $print = ([WMICLASS]“\$serverROOTcimv2:Win32_Printer”).createInstance(

  9. I can’t seem to get this script to work. If I run in from a 2008 R2 box I get the following

    Cannot convert value “\MYSERVERNAMEROOTcimv2:Win32_TCPIPPrinterPort” to type “System.Management.ManagementClass”. Error: “The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)”

    If I change the following from

    $print = ([WMICLASS]”\server$ROOTcimv2:Win32_Printer”).createInstance()

    to

    $print = ([WMICLASS]”\.ROOTcimv2:Win32_Printer”).createInstance()

    it will give a different error. That error is:

    Exception calling “Put” with “0” argument(s): “Invalid parameter ”
    At C:ittestImport.ps1:46 char:10
    + $port.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Any ideas?

  10. I get this message when trying to run the Script from my Win7 Workstation to a 2008 R2 Server but it works fine when PrintServer is a 2003 Server.
    Exception calling “Put” with “0” argument(s): “Generic failure ”
    At C:Bulk Printer Import.ps1:36 char:11
    + $print.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException
    Furthermore there are EventID's 10009 in the System log. Something in Win2008R2 seems to be blocking DCOM Calls. I called MS but they have not been able to tell me how to resolve this.
    Idea?

    • I was getting this error as well. Turns out I used excel to make the CSV, and had put quotes around the driver name. For whatever reason, when I opened the CSV in notepad and looked at it, it had 3 sets of double quotes around the driver name. I deleted two sets of double quotes before and after the driver name, and now the script runs successfully.

  11. $server = $args[0]
    $print = ([WMICLASS]”\$serverROOTcimv2:Win32_Printer”).createInstance()
    $print.drivername = $args[1]
    $print.PortName = $args[2]
    $print.Shared = $true
    $print.Sharename = $args[3]
    $print.Location = $args[4]
    $print.Comment = $args[5]
    $print.DeviceID = $args[6]
    $print.Put()

    Works for me.

  12. The code from the original post works perfect. I am using it now to add 700 printers to a node in my cluster. I can’t add to the virtual instance, but thats easily worked around, export the printers from the node with printMgmt console and import to the Virtual Instance.

    Thanks.

  13. Seem to have some trouble with it and getting several errors..

    Can anyone help me out? Thanks
    Cannot convert value “\ROOT:Win32_TCPIPPrinterPort” to type “System.Management.ManagementClass”. Error: “Invalid parameter”
    At C:UsershexDesktopCreate-Printers.ps1.ps1:41 char:20
    + $port = ([WMICLASS] <<<< "\$serverROOTcimv2:Win32_Printer").createInstance()
    + CategoryInfo: Not Specified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

  14. Hi guys,

    The script works fine under Windows 2k8 R2. Just one issue, the csv file must have the following headers:
    Printserver,Driver,IPAddress,Portname,Sharename,Location,Comment,Printername

    A previous post mentioned the header, nut the IPAddress was missing.

  15. Thank you! This script worked beautifully during a server migration from 2003 x86 to 2008 x64 with about 315 queues. I added another function that calls SetACL.exe (www.sf.net/projects/SetACL) to set perms on each queue since subinacl.exe was being a pain (couldn’t set “manage documents” and “print” permissions at the same time).

  16. I have used this script in the past on a Windows 2008 R2 and it has worked…however all printers were configured with their IP address…We have a new site and i was trying to configure the print server before the printers were moved to the site when i run the script it creates one print queue/port and gets stuck….I am a power shell noob….i know the script is waiting for a response from the printer but it’s not there…can anyone offer any advice

    • Hi Larry, I have the same problem. It only creates 1 queue and then gets stuck. There is a nasty workaround:
      1. Stop the Print Spooler service –> this will cause the script to fail for all other queues
      2. Restart the Print Spooler service
      3. Restart the script –> it will create the next queue, but will get stuck again after that one.

      I did this 60 times to create 60 queues :((

      Did you ever solve this?

  17. Hi, script worked ok, but how to set “Print spooled documents first” too? When you created printer by wizard it’s set by default, but by script is unchecked.

  18. Hi guys

    I am, having troubles. Help please
    function CreatePrinter {
    $server = $args[0]
    $print = ([WMICLASS]”\$serverROOTcimv2:Win32_Printer”).createInstance()
    $print.drivername = “Lexmark Universal PS3″
    $print.PortName = “172.30.29.58”
    $print.Shared = $true
    $print.Sharename = “BNEBCP_HP4250_2″
    $print.Location = BCP/Interactive
    $print.Comment = “Lexmark Universal PS3″
    $print.DeviceID = “BNEBCP_HP4250_2″
    $print.Put()
    }

    • You don’t say what you need help with.. But perhaps adding quotes around “BCP/Interactive” will do the trick. Also the function is still expecting the server name to be passed to it as an argument, even though you’ve “hard coded” the rest of the information.

  19. works for me: server 2008 r2

    function CreatePrinter {
    $server = $args[0]
    $print = ([WMICLASS]“\.ROOTcimv2:Win32_Printer”).createInstance()
    $print.drivername = $args[1]
    $print.PortName = $args[2]
    $print.Shared = $true
    $print.Published = $true
    $print.Sharename = $args[3]
    $print.Location = $args[4]
    $print.Comment = $args[5]
    $print.DeviceID = $args[6]
    $print.Put()
    }

    function CreatePrinterPort {
    $server = $args[0]
    $port = ([WMICLASS]”\.ROOTcimv2:Win32_TCPIPPrinterPort”).createInstance()
    $port.Name= $args[1]
    $port.SNMPEnabled=$false
    $port.Protocol=1
    $port.HostAddress= $args[2]
    $port.Put()
    }

    $printers = Import-Csv “printers.csv”

    foreach ($printer in $printers) {
    CreatePrinterPort $printer.Printserver $printer.Portname $printer.IPAddress
    CreatePrinter $printer.Printserver $printer.Driver $printer.Portname $printer.Sharename $printer.Location $printer.Comment $printer.Printername
    }

    csv tabs:

    Printserver,Driver,Portname,IPAddress,Sharename,Location,Comment,Printername

  20. Works great at creating printers for me too on Server 2008 R2

    However, I have an issue with migrating printers after creating them with this script. After using the script to create the printers I take a “PrintMig” (Printer Migration) of the print queues for importing to a different server (for DR purposes). We plan to use “Internet Printing” on the DR server, formally IPP in Server 2003. However after importing the PrintMig to the new server (both servers are same OS version and spec), the printers show up fine and print with no issues, but they do not show up in the list of “Internet Printers” on the new server, i.e. http://localhost/printers.

    Any printers I create locally on the DR server show up in the Internet Printers list fine. Also, a printer that I created manually on the source server (where I ran the script) and was captured in the PrintMig, this also shows up fine in the Internet Printers list on the DR server.

    This seems very strange. Does anyone know why this is?

    Thanks in advance…

    • Another update on this:
      I have just used this PowerShell script to create printers on my DR print server and the printer objects create fine and the test print works fine. However the printers do not show up in the Internet Pritners list. Does anyone have any idea why this is? Just to note again, printers created manually, i.e. in “Devices and Printers” show up fine in the Internet Printers list.
      Many thanks,
      Glenn.

    • Forget this now, it was actually an error on my part :) I did not have the printer set to “Share”, so this is why it had not showed up in the list of “Internet Printers”…!

      Set your printers to share and all should be fine if you are using this scenario.

  21. Extremly nice Script for PrintServermigration
    Im Installing the Printers on 2008R2.
    The Port will be created, but on the Printerpart i reseve this msg:

    Exception calling “Put” with “0” argument(s): “Generic failure ”
    At D:PrintMigInstall_Printer.ps1:12 char:11
    + $print.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    CSV content:
    Printserver,Driver,Portname,IPAddress,Sharename,Location,Comment,Printername
    SERVERRNTP03,Lexmark Universal PS3,PrinterTEST,10.10.10.10,PrinterTEST,Room3,BlackWihtePrinter,Printername

  22. I am trying to run the following:
    ###########################################################################”
    #
    # NAME: Create-Printers.ps1
    #
    # ORIGINAL AUTHOR: Jan Egil Ring
    # EMAIL: jan.egil.ring@powershell.no
    # BLOG: http://blog.powershell.no
    #
    # REVISING AUTHOR: _____________ (added lines 42 – 44, appended line 63)
    # EMAIL: ______@____________
    #
    # COMMENT: Simple script to bulk-create printers on a print-server. Printers are imported from a csv-file.
    # Running the script from Windows Server 2003 returns an access denied error, possibly due to the impersonation-model in Windows Server 2003.
    # Created and tested from Windows Server 2008 against a remote Windows Server 2003 print-server.
    # Should work from Windows Vista, Windows 7, Windows Server 2008 and Windows Server 2008 R2 against remote print-servers (2000/2003/2008/2008 R2)
    #
    # You have a royalty-free right to use, modify, reproduce, and
    # distribute this script file in any way you find useful, provided that
    # you agree that the creator, owner above has no warranty, obligations,
    # or liability for such use.
    #
    # VERSION HISTORY: 1.0 07.11.2009 – Initial release
    #
    ###########################################################################”

    $DebugPreference = “silentlyContinue”

    $printers = Import-Csv c:\printers.csv

    function CreatePrinter
    {
    $server = $args[0]
    $print = ([WMICLASS]”\\$server\ROOT\cimv2:Win32_Printer”).createInstance()
    $print.drivername = $args[1]
    $print.PortName = $args[2]
    $print.Shared = $true
    $print.Sharename = $args[3]
    $print.Location = $args[4]
    $print.Comment = $args[5]
    $print.DeviceID = $args[6]
    $print.PrintProcessor = $args[7]
    $print.Rawonly = $true
    $print.DoCompleteFirst = $true
    $print.Put()
    }

    function CreatePrinterPort
    {
    $server = $args[0]
    $port = ([WMICLASS]”\\$server\ROOT\cimv2:Win32_TCPIPPrinterPort”).createInstance()
    $port.Name= $args[1]
    $port.SNMPEnabled=$false
    $port.Protocol=1
    $port.HostAddress= $args[2]
    $port.Put()
    }

    foreach ($printer in $printers)
    {
    CreatePrinterPort $printer.Printserver $printer.Portname $printer.IPAddress
    CreatePrinter $printer.Printserver $printer.Driver $printer.Portname $printer.Sharename $printer.Location $printer.Comment $printer.Printername $printer.PrintProcessor
    }

    but I am getting:
    ###########################################################################”
    #
    # NAME: Create-Printers.ps1
    #
    # ORIGINAL AUTHOR: Jan Egil Ring
    # EMAIL: jan.egil.ring@powershell.no
    # BLOG: http://blog.powershell.no
    #
    # REVISING AUTHOR: _____________ (added lines 42 – 44, appended line 63)
    # EMAIL: ______@____________
    #
    # COMMENT: Simple script to bulk-create printers on a print-server. Printers are imported from a csv-file.
    # Running the script from Windows Server 2003 returns an access denied error, possibly due to the impersonation-model in Windows Server 2003.
    # Created and tested from Windows Server 2008 against a remote Windows Server 2003 print-server.
    # Should work from Windows Vista, Windows 7, Windows Server 2008 and Windows Server 2008 R2 against remote print-servers (2000/2003/2008/2008 R2)
    #
    # You have a royalty-free right to use, modify, reproduce, and
    # distribute this script file in any way you find useful, provided that
    # you agree that the creator, owner above has no warranty, obligations,
    # or liability for such use.
    #
    # VERSION HISTORY: 1.0 07.11.2009 – Initial release
    #
    ###########################################################################”

    $DebugPreference = “silentlyContinue”

    $printers = Import-Csv c:\printers.csv

    function CreatePrinter
    {
    $server = $args[0]
    $print = ([WMICLASS]”\\$server\ROOT\cimv2:Win32_Printer”).createInstance()
    $print.drivername = $args[1]
    $print.PortName = $args[2]
    $print.Shared = $true
    $print.Sharename = $args[3]
    $print.Location = $args[4]
    $print.Comment = $args[5]
    $print.DeviceID = $args[6]
    $print.PrintProcessor = $args[7]
    $print.Rawonly = $true
    $print.DoCompleteFirst = $true
    $print.Put()
    }

    function CreatePrinterPort
    {
    $server = $args[0]
    $port = ([WMICLASS]”\\$server\ROOT\cimv2:Win32_TCPIPPrinterPort”).createInstance()
    $port.Name= $args[1]
    $port.SNMPEnabled=$false
    $port.Protocol=1
    $port.HostAddress= $args[2]
    $port.Put()
    }

    foreach ($printer in $printers)
    {
    CreatePrinterPort $printer.Printserver $printer.Portname $printer.IPAddress
    CreatePrinter $printer.Printserver $printer.Driver $printer.Portname $printer.Sharename $printer.Location $printer.Comment $printer.Printername $printer.PrintProcessor
    }

    I have created a csv file with the headers as described above.
    I am running the script on a Windows 7 64 bit machine to add the printers to a Windows 2003 R2 server. Th server has all of the required drivers installed.

    What could I be doing wrong?

  23. Sorry I thought I has pasted in the error(s):

    Exception calling “Put” with “0” argument(s): “Invalid parameter ”
    At C:\Scripts\PowerShell\Create-Printers.ps1:57 char:18
    + $port.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Exception calling "Put" with "0" argument(s): "Generic failure "
    At C:\Scripts\PowerShell\Create-Printers.ps1:45 char:19
    + $print.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Exception calling "Put" with "0" argument(s): "Invalid parameter "
    At C:\Scripts\PowerShell\Create-Printers.ps1:57 char:18
    + $port.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Exception calling "Put" with "0" argument(s): "Generic failure "
    At C:\Scripts\PowerShell\Create-Printers.ps1:45 char:19
    + $print.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Exception calling "Put" with "0" argument(s): "Invalid parameter "
    At C:\Scripts\PowerShell\Create-Printers.ps1:57 char:18
    + $port.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Exception calling "Put" with "0" argument(s): "Generic failure "
    At C:\Scripts\PowerShell\Create-Printers.ps1:45 char:19
    + $print.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Exception calling "Put" with "0" argument(s): "Invalid parameter "
    At C:\Scripts\PowerShell\Create-Printers.ps1:57 char:18
    + $port.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Exception calling "Put" with "0" argument(s): "Generic failure "
    At C:\Scripts\PowerShell\Create-Printers.ps1:45 char:19
    + $print.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

  24. Hey, I also got this error:
    Exception calling “Put” with “0″ argument(s): “Invalid parameter ”
    At C:ittestImport.ps1:46 char:10
    + $port.Put <<<< ()
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    I resolved the problem. The problem was the csv file..
    The csv-file wasnt comma-separeted, it was semicolon-separated, for some reason. So I opened it in notepad and replaced the semicolons with commas, then it worked.

    How can I check the "list in directiories" (in the sharing-tab in properties on the printer) when creating printers? I've set sharing=$true, but that doesnt do it.