none
Create printers in PowerShell with WMI "Win32_Printer" .createInstance()

    Question

  • Hi,

    I'm trying to create a printer with PowerShell and WMI "Win32_Printer" .createInstance() ...

    Once I've worked out how to do this I'm hoping to import from CSV (I originally tried a script from http://blog.powershell.no but that has the same issue.)

    here's the code ...

    $print = [WMICLASS]"Win32_Printer"
    $newprinter = $print.createInstance() 
    $newprinter.drivername = "HP Laserjet 4300 PCL 6"
    $newprinter.PortName = "IP_172.19.99.1"
    $newprinter.Shared = $true
    $newprinter.Sharename = "ShareName"
    $newprinter.Location = "Trowbridge"
    $newprinter.Comment = "Comment"
    $newprinter.DeviceID = "DeviceID"
    $newprinter.Put() 

    I get the error "Exception calling "Put" with "0" argument(s): "Generic failure "

    I've read posts about PowerShell 2 having a bug with .Put with .createInstance ....

    I'm running this on Server 2008 R2

    Name                           Value
    ----                           -----
    CLRVersion                     2.0.50727.4927
    BuildVersion                   6.1.7600.16385
    PSVersion                      2.0
    WSManStackVersion              2.0
    PSCompatibleVersions           {1.0, 2.0}
    SerializationVersion           1.1.0.1
    PSRemotingProtocolVersion      2.1


    Any anyone help me?

     

    • Edited by John Grenfell Tuesday, January 26, 2010 2:59 PM weird formating
    Tuesday, January 26, 2010 2:55 PM

Answers

  • When I was trying this initially I wasn't typing in the driver name exactly as it was installed and it was erroring. If you open up Printers and then go to File | Server Properties and look under the tab for Drivers and make sure it's there and spelled exactly the same in your script. Ditto for the Port - it should also be listed as installed (even if it already is the script will still work).
    The script above certainly worked in my test environment, albeit that was 32 bit.
    I don't know about 64 bit though. As part of the driver installation you'll probably have to install both 32bit and 64 bit versions (using different .INF paths), and if the drivers have the same name then the print queue installation will use the driver application to the current machine (e.g. 64 bit) but because the queue is shared then any 32 bit clients connecting will download the 32 bit version. In theory.
    Can't help you with PS but there is a parameter: -EnableAllPrivileges (in CTP 2) which you can add to your Get-WMIobject which sounds like it does the trick.

    • Marked as answer by John Grenfell Wednesday, January 27, 2010 1:28 PM
    Wednesday, January 27, 2010 12:52 PM

All replies

  • If it's on a Server o/s you'll probably need to boost your rights to install drivers. I'm not into PS but in VBS terms:
    Set objPrinter = GetObject( _
        "winmgmts:{impersonationLevel=Impersonate ," _
        & "(LoadDriver)}!//./root/cimv2:Win32_Printer")
    http://msdn.microsoft.com/en-us/library/aa390428(VS.85).aspx


    If you're trying to set up printers on a server based on an existing server then you could look at the PrintMig tool downloadable from Microsoft. It essentially zips up all your existing print queues, drivers, and ports and allows you to unzip them onto another server.
    Tuesday, January 26, 2010 3:57 PM
  • Does a printer port named "IP_172.19.99.1" exist on the machine?
    Uros Calakovic
    Tuesday, January 26, 2010 4:12 PM
    Moderator
  • Yes, both the driver and printer port both exist on the server.
    Wednesday, January 27, 2010 9:03 AM
  • I do love PrintMig but I'm migrating 12 novell Netware print servers to Server 2008 R2. All the data is held quite nicely in a csv file.

    I'm running powershell via "Run as administrator" ... I had hoped it would be able to 'do' everything.

    In VBS term's if you ran a cmd box via "Run as administrator" and then executed a vbs script would you need to do the impersonationlevel?

    Wednesday, January 27, 2010 9:12 AM
  • strComputer="."
    Set objWMIService=GetObject("winmgmts:" _
        & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    
    Set objPrinter=objWMIService.Get("Win32_Printer").SpawnInstance_
    objPrinter.Security_.Privileges.AddAsString "SeLoadDriverPrivilege", True
    objPrinter.DeviceID="My New Printer"
    objPrinter.DriverName="HP Laserjet 4300 PCL 6"
    objPrinter.PortName="IP_172.19.99.1"
    objPrinter.Comment="Comment"
    objPrinter.Shared=True
    objPrinter.ShareName="Sharename"
    objPrinter.Put_
    
    The default is, I believe, impersonation. The problem is the ability to load drivers which you need to add, either as the example I gave, or by by adding the privilege as a string, e.g.
     
    Wednesday, January 27, 2010 10:50 AM
  • Scrap that - I fired up a Windows 2008 Server to try this and it has got unbelievably harder to script installing printers! Apologies.
    The problem is the driver. In the end I opened up C:\Windows\inf\prnhp001.inf to get the EXACT name for a driver - if you want to use a manufacturer's driver then look to the comment in the code below. This code DOES work!
    Good luck John.

    Dim strShareName 
    
    strComputer = "."
    strQueue = "My New Print Queue"
    strDriver = "HP LaserJet 8000 Series PCL 5"
    strPort = "172.19.99.2"
    strComment = "Comment"
    strLocation = "Trowbridge"
    strShareName = "My New Print Queue Share"
    
    Set objWMIService = GetObject("winmgmts:" _
       & "{impersonationLevel=impersonate,(LoadDriver)}!\\" & strComputer & "\root\cimv2")
    
    	' Create port
    Set objNewPort = objWMIService.Get("Win32_TCPIPPrinterPort").SpawnInstance_
    objNewPort.Name = "IP_" & strPort
    objNewPort.Protocol = 1
    objNewPort.HostAddress = strPort
    objNewPort.PortNumber = "9100"
    objNewPort.SNMPEnabled = False
    objNewPort.Put_
    
    	' Add driver
    Set objDriver = objWMIService.Get("Win32_PrinterDriver")
    objDriver.Name = strDriver 
    objDriver.SupportedPlatform = "Windows NT x86"
    objDriver.Version = "3"
    	' use the property below if not installed in Windows
    'objInfname = "\\server\share\driver\oem.inf"
    intResult = objDriver.AddPrinterDriver(objDriver)
    If intResult<>0 Then
    	WScript.Echo "Failed to add driver: " & strDriver
    	WScript.Quit
    End If
    
    	' Create queue
    Set objPrinter = objWMIService.Get("Win32_Printer").SpawnInstance_
    objPrinter.DriverName = strDriver
    objPrinter.PortName   = "IP_" & strPort
    objPrinter.DeviceID   = strQueue
    objPrinter.Location = strLocation
    objPrinter.Comment = strComment
    objPrinter.Network = True
    If strShareName<>"" Then
    	objPrinter.Shared = True
    	objPrinter.ShareName = strShareName
    End If
    objPrinter.Put_
    Wednesday, January 27, 2010 11:54 AM
  • I've can see what you're saying about the impersonationLevel stuff .... Any ideas on how to do this with Powershell? I looked at this  http://www.microsoft.com/technet/scriptcenter/topics/winpsh/wmiin2.mspx and it talks about –authentication 6 on the wmi-objects ... am I on the right track?

    I've tried using my script with different drivers (all of which are installed) .. my only slight concern is that I have both 64 and 32 bit drivers which both have the same driver name. This make me wonder how do I tell it which driver to use? 32 bit or 64 drivers or both?
    Wednesday, January 27, 2010 11:57 AM
  • When I was trying this initially I wasn't typing in the driver name exactly as it was installed and it was erroring. If you open up Printers and then go to File | Server Properties and look under the tab for Drivers and make sure it's there and spelled exactly the same in your script. Ditto for the Port - it should also be listed as installed (even if it already is the script will still work).
    The script above certainly worked in my test environment, albeit that was 32 bit.
    I don't know about 64 bit though. As part of the driver installation you'll probably have to install both 32bit and 64 bit versions (using different .INF paths), and if the drivers have the same name then the print queue installation will use the driver application to the current machine (e.g. 64 bit) but because the queue is shared then any 32 bit clients connecting will download the 32 bit version. In theory.
    Can't help you with PS but there is a parameter: -EnableAllPrivileges (in CTP 2) which you can add to your Get-WMIobject which sounds like it does the trick.

    • Marked as answer by John Grenfell Wednesday, January 27, 2010 1:28 PM
    Wednesday, January 27, 2010 12:52 PM
  • Yippe!!!

    I'm an idiot! .... You were spot on. The problem was in between the computer and the chair.

    I think during my testing of creating printers/ports I dropped the IP_ from my ports ... when I scanned the ports I had a combination of IP_xxx.xxx.xxx.xxx and xxx.xxx.xxx.xxx ...

    Thanks for all your help .....
    Wednesday, January 27, 2010 1:28 PM
  • can you post the final script you used?
    Tuesday, March 2, 2010 5:19 AM
  • Hi,

    Here's my script ... it's a little rough around the edges but created 200 printers for me quite nicely ... you do did to make sure you have the driver name correct ... and if it's not a driver the OS knows about you'll have to install before running ... ie grab a driver from HP and install first ;o)

    function CreatePrinter {
    
    $server = $args[0]
    $print = [WMICLASS]"Win32_Printer"
    $newprinter = $print.createInstance() 
    $newprinter.drivername = $args[1]
    $newprinter.PortName = $args[2]
    $newprinter.Shared = $true
    $newprinter.Sharename = $args[3]
    $newprinter.Location = $args[4]
    $newprinter.Comment = $args[5]
    $newprinter.DeviceID = $args[6]
    Write-Host "Creating Printer $printer" -foregroundcolor "green"
    $newprinter.Put()
    
    }
    
    function CreatePrinterPort {
    $server =  $args[0] 
    $port = [wmiclass]"Win32_TcpIpPrinterPort"
    $newPort = $port.CreateInstance()
    $newport.Name= $args[1]
    $newport.SNMPEnabled=$false 
    $newport.Protocol=1 
    $newport.HostAddress= $args[2] 
    Write-Host "Creating Port $newport.HostAddress" -foregroundcolor "green"
    $newport.Put() 
    }
    
    $printers = Import-Csv c:\scripts\Tr-Mod2.csv
    
    foreach ($printer in $printers) {
    CreatePrinterPort trp $printer.Portname $printer.Portname
    CreatePrinter trp $printer.Driver $printer.Portname $printer.Sharename $printer.Sharename $printer.Comment $printer.Sharename
    }
    
    Let me know how you get on ;o)

    J
    Tuesday, March 2, 2010 10:29 AM
  • Hey John,

    I am trying to use the script you created above and I am getting the exact error you recieved at the beginning of this thread.  I went through and see that this may be an error on how the ports or drivername is listed.  As far as I can tell I am using the correct driver name that I copied out of the print server and hard coded in to the script and the IP is listed correctly.  I was wondering what exactly did you change in you situation so I can better understand what exactly i am missing?

    Thank you

    Tuesday, April 20, 2010 10:17 PM
  • Hi Jason,

    From memory my two issues were related to me using the wrong printer port name during testing and also having the wrong driver name.

    If Windows doesn’t ship with the driver your trying to use install it before trying to script the creation. I found it best to open the driver inf file and copy/paste it into the code/cvs file.

    If you're happy to post the code I'll cast my eye over it for you, but I am bit of a noob and slammed with work so apologies if it takes me a while to get back to you ;o)

    J

    Wednesday, April 21, 2010 7:47 AM
  • Thanks for the response!

    I actually found the issue I was having and feel a bit like a noob myself.  It skipped my mind that the above script was running locally and not on the server i wanted even though the $server variable was present.  I switched the code to look like the following

    $print = [WMICLASS]"\\$server\root\cimv2:Win32_Printer "

    It came down to the local machine didn't have the driver I was specifying and it was causing the error you saw before.  Once I switched it to the print server it worked great.

    Thank you again

     

    Wednesday, April 21, 2010 5:08 PM
  • Here is my script for vista / windows 7 (64 bit version :-))
    I use the build in vbs scripts located under C:\Windows\System32\Printing_Admin_Scripts\en-US\ (a lot easier)

    The options/syntax for the vbs scripts are available on : http://technet.microsoft.com/en-us/library/cc754632(WS.10).aspx

    Change SERVERNAME with your location of the install files
    Save the script as a .bat file!

    Any remarks are welcome.
    Hope this helps a bit.

    -------
    @REM ADD DRIVERS FOR WINDOWS 7 64 BIT

    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prndrvr.vbs -a -m "RICOH Aficio MP C4000 RPCS" -v 3 -e "Windows x64" -i "\\SERVERNAME\Install\Drivers\A_Printer Drivers\RICOH MPC4000\DRIVERS\RPCS\WIN7 64bit\Disk1\RCA8E164.inf"
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnport.vbs -a -r IP_10.20.1.231 -h 10.20.1.231 -o raw -n 9100
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnmngr.vbs -a -p "RICOH MPC4000 _ RECEPTION - COLOR" -m "RICOH Aficio MP C4000 RPCS" -r "IP_10.20.1.231"
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnmngr.vbs -a -p "RICOH MPC4000 _ RECEPTION - BLACK" -m "RICOH Aficio MP C4000 RPCS" -r "IP_10.20.1.231"
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnport.vbs -a -r IP_10.20.1.230 -h 10.20.1.230 -o raw -n 9100
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnmngr.vbs -a -p "RICOH MPC4000 _ MARKETING - COLOR" -m "RICOH Aficio MP C4000 RPCS" -r "IP_10.20.1.230"
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnmngr.vbs -a -p "RICOH MPC4000 _ MARKETING - BLACK" -m "RICOH Aficio MP C4000 RPCS" -r "IP_10.20.1.230"

    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prndrvr.vbs -a -m "RICOH Aficio MP C4500 RPCS" -v 3 -e "Windows x64" -i "\\SERVERNAME\Install\Drivers\A_Printer Drivers\NRG MPC4500\RPCS\WIN7 64bit\Disk1\RC96E164.inf"
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnport.vbs -a -r IP_10.20.1.233 -h 10.20.1.233 -o raw -n 9100
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnmngr.vbs -a -p "RICOH MPC4500 _ FINANCE - COLOR" -m "RICOH Aficio MP C4500 RPCS" -r "IP_10.20.1.233"
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnmngr.vbs -a -p "RICOH MPC4500 _ FINANCE - BLACK" -m "RICOH Aficio MP C4500 RPCS" -r "IP_10.20.1.233"

    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prndrvr.vbs -a -m "PCL6 Driver for Universal Print" -v 3 -e "Windows x64" -i "\\SERVERNAME\Install\Drivers\A_Printer Drivers\NRG DSm745\PCL6\WIN7 64bit\disk1\oemsetup.inf"
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnport.vbs -a -r IP_10.20.1.238 -h 10.20.1.238 -o raw -n 9100
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnmngr.vbs -a -p "NRG DSm745 _ PURCHASE - BLACK" -m "PCL6 Driver for Universal Print" -r "IP_10.20.1.238"
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnport.vbs -a -r IP_10.20.1.239 -h 10.20.1.239 -o raw -n 9100
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnmngr.vbs -a -p "NRG DSm745 _ PURCHASE SANDRA - BLACK" -m "PCL6 Driver for Universal Print" -r "IP_10.20.1.239"

    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prndrvr.vbs -a -m "RICOH Aficio SP C420DN RPCS" -v 3 -e "Windows x64" -i "\\SERVERNAME\Install\Drivers\A_Printer Drivers\RICOH SPC420DN\english\DRIVERS\RPCS\WIN7 64bit\Disk1\RCB2E164.inf"
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnport.vbs -a -r IP_10.20.1.240 -h 10.20.1.240 -o raw -n 9100
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnmngr.vbs -a -p "RICOH SPC420DN _ IT - BLACK" -m "RICOH Aficio SP C420DN RPCS" -r "IP_10.20.1.240"
    Cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\Prnmngr.vbs -a -p "RICOH SPC420DN _ IT - COLOR" -m "RICOH Aficio SP C420DN RPCS" -r "IP_10.20.1.240"

    pause
    ---------

    Friday, May 14, 2010 10:08 AM
  • Scrap that - I fired up a Windows 2008 Server to try this and it has got unbelievably harder to script installing printers! Apologies.
    The problem is the driver. In the end I opened up C:\Windows\inf\prnhp001.inf to get the EXACT name for a driver - if you want to use a manufacturer's driver then look to the comment in the code below. This code DOES work!
    Good luck John.

    Dim strShareName 
    
    
    
    strComputer = "."
    
    strQueue = "My New Print Queue"
    
    strDriver = "HP LaserJet 8000 Series PCL 5"
    
    strPort = "172.19.99.2"
    
    strComment = "Comment"
    
    strLocation = "Trowbridge"
    
    strShareName = "My New Print Queue Share"
    
    
    
    Set objWMIService = GetObject("winmgmts:" _
    
      & "{impersonationLevel=impersonate,(LoadDriver)}!\\" & strComputer & "\root\cimv2")
    
    
    
    	' Create port
    
    Set objNewPort = objWMIService.Get("Win32_TCPIPPrinterPort").SpawnInstance_
    
    objNewPort.Name = "IP_" & strPort
    
    objNewPort.Protocol = 1
    
    objNewPort.HostAddress = strPort
    
    objNewPort.PortNumber = "9100"
    
    objNewPort.SNMPEnabled = False
    
    objNewPort.Put_
    
    
    
    	' Add driver
    
    Set objDriver = objWMIService.Get("Win32_PrinterDriver")
    
    objDriver.Name = strDriver 
    
    objDriver.SupportedPlatform = "Windows NT x86"
    
    objDriver.Version = "3"
    
    	' use the property below if not installed in Windows
    
    'objInfname = "\\server\share\driver\oem.inf"
    
    intResult = objDriver.AddPrinterDriver(objDriver)
    
    If intResult<>0 Then
    
    	WScript.Echo "Failed to add driver: " & strDriver
    
    	WScript.Quit
    
    End If
    
    
    
    	' Create queue
    
    Set objPrinter = objWMIService.Get("Win32_Printer").SpawnInstance_
    
    objPrinter.DriverName = strDriver
    
    objPrinter.PortName  = "IP_" & strPort
    
    objPrinter.DeviceID  = strQueue
    
    objPrinter.Location = strLocation
    
    objPrinter.Comment = strComment
    
    objPrinter.Network = True
    
    If strShareName<>"" Then
    
    	objPrinter.Shared = True
    
    	objPrinter.ShareName = strShareName
    
    End If
    
    objPrinter.Put_

    This works well, except if you are installing the drivers, it should be:

    objDriver.Infname = "\\server\share\driver\oem.inf"

    otherwise the driver won't install.

    Thanks!

    Monday, October 18, 2010 1:41 PM
  • Hey John, I know this is an old post but I do have a quick question. Do you have an example of the CSV file, Tr-Mod2.csv in your script?
    Saturday, June 18, 2011 3:00 AM
  • Hi,

    No problem .. the contents looked like this ...

     Sharename,Portname,Driver,Comment
    LA-S22B-HP1280,172.21.99.46,HP Deskjet 1280,WORKROOM
    LA-T002-HP1280C,172.21.99.74,HP Deskjet 1280,SS
    CH-A24-HP4,172.23.99.19,HP LaserJet 4,
    CH-C110C-HP4,172.23.99.31,HP LaserJet 4,WORKROOM
    CH-D8-HP4,172.23.99.63,HP LaserJet 4,ESTAT
    LA-A3-HP4,172.21.99.57,HP LaserJet 4,WORKROOM
    LA-F1-HP4,172.21.99.45,HP LaserJet 4,FARM
    LA-T001-HP4,172.21.99.13,HP LaserJet 4,
    TR-L15-HP4,172.20.99.14,HP LaserJet 4,ERT
    CH-B5A-HP4050,172.23.99.48,HP LaserJet 4000 Series PCL 6,WORKROOM
    CH-C4A-HP4050,172.23.99.25,HP LaserJet 4000 Series PCL 6,SS
    CH-D005A-HP4000,172.23.99.113,HP LaserJet 4000 Series PCL 6,ESTAT
    CH-D1-HP4000,172.23.99.49,HP LaserJet 4000 Series PCL 6,WORKROOM

    I feel like I've been living and breathing powershell for the last year now so I think I could rework the script quite a lot now but once the job's done it rarely needs doing again :o) ...

    Let me know how you get on and I'll help where I can.

     

    J

    Saturday, June 18, 2011 8:47 AM
  • If it's on a Server o/s you'll probably need to boost your rights to install drivers. I'm not into PS but in VBS terms:
    Set objPrinter = GetObject( _
        "winmgmts:{impersonationLevel=Impersonate ," _
        & "(LoadDriver)}!//./root/cimv2:Win32_Printer")
    http://msdn.microsoft.com/en-us/library/aa390428(VS.85).aspx


    If you're trying to set up printers on a server based on an existing server then you could look at the PrintMig tool downloadable from Microsoft. It essentially zips up all your existing print queues, drivers, and ports and allows you to unzip them onto another server.

    I realize this is an old thread, but, I was hitting my head against the wall trying to figure this out, until I added one line of code that made everything work:

    $driverclass = [wmiclass]"Win32_PrinterDriver"
    ### The main line
    $driverclass.Scope.Options.EnablePrivileges = $true
    ###             ^^^^^^^^^^^^^^^^
    $driver = $driverclass.CreateInstance()

    Setting that scope fixed it for me. Hope that helps others :)


    Custom-built beauty: Highpoint 2460x4 - 4x2TB RAID-5 Hitachi Enterprise (5.76TB) nVidia Sil3441 - 2x1TB RAID-0 Samsung Enterprise (1.54TB) HP NC360T LACP team - 2Gbps Netgear GS108Tv2 DD-wrt backbone - open-source rules

    Monday, July 30, 2012 4:16 PM