Jump to content

SOLVED: Printer install "script" And SCCM


Recommended Posts

I have an AutoIt script I wrote so that users can select printers to install from a treeview list. The installer works great if run manually and the user has admin rights and can elevate. However if I advertise it to systems via SCCM it will only install the TCP/IP port and the printer driver, when it reaches the point to install the printer it fails with an WMI access denied error. The script is running under the System account so permissions should not really be an issue.

Any SCCM experts out there, or anyone have any ideas? Below is the source code.

And before anyone suggests it, I do not have a print server :( therfore i cannot advertise printers via AD, or any of those other much easier methods of getting printers on machine which are on a shared system such as GPO preferences. They are all direct connected TCP/IP printers. :( I've not tried running this specific version of the script via a startup script but have used pieces of it in the past so that part works.

edit: I forgot to mention, no I will not be able to give standard users rights to install printers.

Edit: code replaced with final code, compiled EXE posted. An other information.

As I said in my post I found a solution, apparently NT Authority/System apparently does not have Write permissions to Win32_Printer in WMI. So the following piece of code to install the printer had to be change from using WMI to us the printui.dll entry point.

Func InstallPrinter($oemDriverName, $strNewPortName, $strPrinterName, $strPrinterLocation ="", $strComment = "", $Default = "False")
ConsoleWrite($oemDriverName & " " & $strNewPortName & " " & $strPrinterName & " " & $strPrinterLocation & " " & $strComment & " " & $Default & @CRLF)
$OBJPRINTER.DriverName = $oemDriverName
$OBJPRINTER.PortName = $strNewPortName
$OBJPRINTER.DeviceID = "myprinter";$strPrinterName
;$OBJPRINTER.Location = $strPrinterLocation
;$OBJPRINTER.Comment = $strComment
$OBJPRINTER.Network = True
ConsoleWrite("Printer Install Result: " & $OBJPRINTER.Put_)
ConsoleWrite(@CRLF)
If StringUpper($Default) = "TRUE" Then
$OBJPRINTER.SetDefaultPrinter()
EndIf
EndFunc ;==>InstallPrinter

Final code:

#RequireAdmin
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_icon=NetPrinter.ico
#AutoIt3Wrapper_outfile=PrinterInstaller.exe
#AutoIt3Wrapper_Res_Comment=Multiple printer Installer
#AutoIt3Wrapper_Res_Fileversion=1.0.0.0
#AutoIt3Wrapper_Res_LegalCopyright=2010 University of Notre Dame
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include "_XMLDomWrapper3.0.au3"
#include <Process.au3>
#include <GUIConstants.au3>
#include <GuiConstantsEx.au3>
#include <GuiTreeView.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <GuiMenu.au3>
#include <WinAPI.au3>

AutoItSetOption("ExpandEnvStrings", 1)

#Region Declarations
Const $TVM_GETITEM = $TV_FIRST + 12

Global $STRCOMPUTER = "."
Global $objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Global $colPrinters = $objWMIService.ExecQuery("Select * from Win32_Printer")
Global $colTCPPorts = $objWMIService.ExecQuery("Select * from Win32_TCPIPPrinterPort")
$objWMIService.Security_.Privileges.AddAsString("SeLoadDriverPrivilege", True)
Global $colPrintersDrivers = $objWMIService.ExecQuery("Select * from Win32_PrinterDriver")
Global $arrPrinters[$colPrinters.Count][5]
If $colTCPPorts.Count > 0 Then
Global $arrTCPPorts[$colTCPPorts.Count][5]
Else
Global $arrTCPPorts[1][4]
$arrTCPPorts[0][1] = "None"
EndIf
Global $arrInstalledDrivers[$colPrintersDrivers.count][4]
Global $OBJNEWPORT = $objWMIService.get("Win32_TCPIPPrinterPort" ).SpawnInstance_
Global $OBJPRINTER = $objWMIService.Get("Win32_Printer" ).SpawnInstance_
Global $OBJDRIVER = $objWMIService.Get("Win32_PrinterDriver")

Global $arrNewPorts[1][5]
Global $arrNewDrivers[1][7]
Global $arrNewPrinters[1][4]
Global $AutoInstall
Global $WindowTitle
Global $fDblClk
Global $structPrinter
Local $STR = "char[256];char[256];char[256];char[256];uint;char[5];char[256];char[256];char[256];uint;char[256];uint;char[5];char[5];char[256];char[256];char[256];char[5];char[5]"
Global $Printers[1]
Global $Parent[1]
Global $Child[1]
Global $parentCHK[1]
Global $ChildCHK[1]
Global $ConfigSettings

if $cmdline[0] = 0 then
$ConfigSettings = "PrinterInstaller.xml"
else
$ConfigSettings = $cmdline[1]
EndIf
LoadSettings($ConfigSettings)
$Parent[0] = UBound($Parent) - 1
GetInstalledPrinterInfo()

Local $Parent_Split = $Parent
Local $btnInstall

Local $mnuFile
Local $mnuExit
Local $mnuPorts
Local $mnuAllPorts, $mnuNewPorts
Local $mnuDrivers
Local $mnuAllDrivers, $mnuNewDrivers
Local $mnuPrinters
Local $mnuAllPrinters, $mnuNewPrinters
Local $mnuHelp
Local $mnuAbout
#EndRegion Declarations

#Region MAIN
Global $mainWindow = GUICreate($WindowTitle, 460, 330)
$mnuFile = GUICtrlCreateMenu("&File")
$mnuExit = GUICtrlCreateMenuItem("Exit", $mnuFile)

$mnuPorts = GUICtrlCreateMenu("&Ports")
$mnuListPorts = GUICtrlCreateMenuItem("List Installed TCP Ports", $mnuPorts)
$mnuNewPorts = GUICtrlCreateMenuItem("List TCP Ports to Install", $mnuPorts)
$mnuAllPorts = GUICtrlCreateMenuItem("Install All Ports", $mnuPorts)

$mnuDrivers = GUICtrlCreateMenu("&Drivers")
$mnuListDrivers = GUICtrlCreateMenuItem("List Installed Drivers", $mnuDrivers)
$mnuNewDrivers = GUICtrlCreateMenuItem("List Drivers to Install", $mnuDrivers)
$mnuAllDrivers = GUICtrlCreateMenuItem("Install All Drivers", $mnuDrivers)

$mnuPrinters = GUICtrlCreateMenu("&Printers")
$mnuListPrinters = GUICtrlCreateMenuItem("List Installed Printers", $mnuPrinters)
$mnuNewPrinters = GUICtrlCreateMenuItem("List Printers to Install", $mnuPrinters)
$mnuAllPrinters = GUICtrlCreateMenuItem("Install All Printers", $mnuPrinters)
$mnuHelp = GUICtrlCreateMenu("&Help")
$mnuAbout = GUICtrlCreateMenuItem("&About", $mnuHelp)

Global $TreeView = GUICtrlCreateTreeView(10, 10, 440, 250, BitOR($GUI_SS_DEFAULT_TREEVIEW, $TVS_CHECKBOXES), $WS_EX_DLGMODALFRAME + $WS_EX_CLIENTEDGE)
GUICtrlSetFont(-1, 12)

$btnInstall = GUICtrlCreateButton("Install", 10, 270, 440, 30)
GUICtrlSetFont(-1, 14, 800)

Dim $Tree_Parent_Split[$Parent_Split[0] + 1]
$z = 0
For $X = 1 To $Parent_Split[0]
$Tree_Parent_Split[$X] = GUICtrlCreateTreeViewItem($Parent_Split[$X], $TreeView)
If $parentCHK[$X] Then GUICtrlSetState(-1, $GUI_CHECKED)

$Child_Split = StringSplit($Child[$X], "|")
Dim $Tree_Child_Split[$Child_Split[0] + 1]
For $y = 1 To $Child_Split[0]
$z += 1
$Tree_Child_Split[$y] = GUICtrlCreateTreeViewItem($Child_Split[$y], $Tree_Parent_Split[$X])
If $ChildCHK[$z] Or $parentCHK[$X] Then GUICtrlSetState(-1, $GUI_CHECKED)
Next

Next

If StringUpper($AutoInstall) = "TRUE" Then
InstallPrinters()
Exit (0)
EndIf

GUISetState()
GUIRegisterMsg($WM_NOTIFY, "MY_WM_NOTIFY")
frmMainWinProc()
GUIRegisterMsg($WM_NOTIFY, "")

#EndRegion MAIN
Func InstallPrinters()
ConsoleWrite("List Count: " & _GUICtrlTreeView_GetCount($TreeView) & @CRLF)
ConsoleWrite("list start: " & $TreeView & @CRLF)
Local $ListItem = 0
For $X = $TreeView + 2 To $TreeView + _GUICtrlTreeView_GetCount($TreeView) + 1
SplashTextOn ("Installing Selected printers", "Installing printer: " & _GUICtrlTreeView_GetText($TreeView, $X),200,100)
ConsoleWrite("Index: " & $X & " Text:" & _GUICtrlTreeView_GetText($TreeView, $X) & " checked: " & _GUICtrlTreeView_GetChecked($TreeView, $X) & " Parent: " & _GUICtrlTreeView_GetParentHandle($TreeView, $X) & " My Handle: " & _GUICtrlTreeView_GetItemHandle($TreeView, $X) & @CRLF)
if (_GUICtrlTreeView_GetParentHandle($TreeView, $X) <> 0) And _GUICtrlTreeView_GetChecked($TreeView, $X) Then
$ListItem += 1
ConsoleWrite("Install: " & $X & @CRLF)

if (Not CheckForDriver(DllStructGetData($Printers[$ListItem], 3))) Or DllStructGetData($Printers[$ListItem], 14) Then
InstallDriver(DllStructGetData($Printers[$ListItem], 3), DllStructGetData($Printers[$ListItem], 4), DllStructGetData($Printers[$ListItem], 5), DllStructGetData($Printers[$ListItem], 6), DllStructGetData($Printers[$ListItem], 7), DllStructGetData($Printers[$ListItem], 8), DllStructGetData($Printers[$ListItem], 15))
EndIf
InstallNewPort(DllStructGetData($Printers[$ListItem], 9), DllStructGetData($Printers[$ListItem], 10), DllStructGetData($Printers[$ListItem], 11), DllStructGetData($Printers[$ListItem], 12), DllStructGetData($Printers[$ListItem], 13))
InstallPrinter(DllStructGetData($Printers[$ListItem], 3), DllStructGetData($Printers[$ListItem], 9), DllStructGetData($Printers[$ListItem], 2), DllStructGetData($Printers[$ListItem], 16), DllStructGetData($Printers[$ListItem], 17), DllStructGetData($Printers[$ListItem], 18))

ElseIf _GUICtrlTreeView_GetParentHandle($TreeView, $X) <> 0 Then
$ListItem += 1

EndIf
Next
SplashOff()
EndFunc ;==>InstallPrinters

Func CheckForDriver($FindMe)
If _ArraySearch($arrInstalledDrivers, $FindMe, 0, 0, 0, 0, 1, 0) = -1 Then
ConsoleWrite("CheckForDriver: False" & @CRLF)
Return False
Else
ConsoleWrite("CheckForDriver: True" & @CRLF)
Return True
EndIf
EndFunc ;==>CheckForDriver

Func GetInstalledPrinterInfo()

Local $X = -1
;~ $arrPrinters[$X][0] = "Name"
;~ $arrPrinters[$X][1] = "PortName"
;~ $arrPrinters[$X][2] = "DriverName"
;~ $arrPrinters[$X][3] = "Location"
;- $arrPrinters[$X][4] = "Comment"
For $InstPrinter In $colPrinters
$X += 1
$arrPrinters[$X][0] = $InstPrinter.Name
$arrPrinters[$X][1] = $InstPrinter.PortName
$arrPrinters[$X][2] = $InstPrinter.DriverName
$arrPrinters[$X][3] = $InstPrinter.Location
$arrPrinters[$X][4] = $InstPrinter.Comment
Next
$X = -1
;~ $arrTCPPorts[$x][0] = "Caption"
;~ $arrTCPPorts[$x][1] = "Protocol"
;~ $arrTCPPorts[$x][2] = "HostAddress"
;~ $arrTCPPorts[$x][3] = "PortNumber"
;~ $arrTCPPorts[$x][4] = "SNMPEnabled"
For $instTCPPorts In $colTCPPorts
$X += 1
$arrTCPPorts[$X][0] = $instTCPPorts.Caption
$arrTCPPorts[$X][1] = $instTCPPorts.Protocol
$arrTCPPorts[$X][2] = $instTCPPorts.HostAddress
$arrTCPPorts[$X][3] = $instTCPPorts.PortNumber
$arrTCPPorts[$X][4] = $instTCPPorts.SNMPEnabled
Next
$X = -1
;~ $arrInstalledDrivers[$x][0] = "Driver Name"
;~ $arrInstalledDrivers[$x][1] = "Type"
;~ $arrInstalledDrivers[$x][2] = "Targetted OS"
For $InstalledPrinterDriver In $colPrintersDrivers
$X += 1
$arrTemp = StringSplit($InstalledPrinterDriver.name, ",")
$arrInstalledDrivers[$X][0] = $arrTemp[1]
$arrInstalledDrivers[$X][1] = $arrTemp[2]
$arrInstalledDrivers[$X][2] = $arrTemp[3]
Next
EndFunc ;==>GetInstalledPrinterInfo

Func InstallNewPort($strNewPortName, $strProtocol, $strHostAddress, $strPortNumber, $strSNMPEnabled)
ConsoleWrite($strNewPortName & " " & $strProtocol & " " & $strHostAddress & " " & $strPortNumber & " " & $strSNMPEnabled & @CRLF)
If $strHostAddress = "" Then
$strHostAddress = $strNewPortName
EndIf
$RECONFIGURED = True
$OBJNEWPORT.Name = $strNewPortName
$OBJNEWPORT.Protocol = $strProtocol
$OBJNEWPORT.HostAddress = $strHostAddress
$OBJNEWPORT.PortNumber = $strPortNumber
$OBJNEWPORT.SNMPEnabled = $strSNMPEnabled
ConsoleWrite("Port install result: " & $OBJNEWPORT.Put_)
ConsoleWrite(@CRLF)
EndFunc ;==>InstallNewPort

Func InstallDriver($oemDriverName, $Platform, $Version, $CopyLocal, $Source, $Destination, $INFName)
ConsoleWrite($oemDriverName & " " & $Platform & " " & $Version & " " & $CopyLocal & " " & $Source & " " & $Destination & " " & $INFName & @CRLF)
If $CopyLocal = True Then
ConsoleWrite('xcopy "' & $Source & "\*.*" & '" "' & $Destination & '\" /e /y /g /h /r /z' & @CRLF)
_RunDOS('xcopy "' & $Source & "\*.*" & '" "' & $Destination & '\" /e /y /g /h /r /z')
EndIf
$OBJDRIVER.Name = $oemDriverName
$OBJDRIVER.SupportedPlatform = $Platform
$OBJDRIVER.Version = $Version
If $CopyLocal Then
$OBJDRIVER.Filepath = StringReplace($Destination, "\", "\\")
Else
$OBJDRIVER.Filepath = StringReplace($Source, "\", "\\")
EndIf
$OBJDRIVER.InfName = $OBJDRIVER.Filepath & "\\" & $INFName
ConsoleWrite($OBJDRIVER.Name & " " & $OBJDRIVER.SupportedPlatform & " " & $OBJDRIVER.Version & " " & $OBJDRIVER.Filepath & " " & $OBJDRIVER.InfName & @CRLF)
ConsoleWrite("Driver Install result: " & $OBJDRIVER.AddPrinterDriver($OBJDRIVER))
ConsoleWrite(@CRLF)
EndFunc ;==>InstallDriver

Func InstallPrinter($oemDriverName, $strNewPortName, $strPrinterName, $strPrinterLocation ="", $strComment = "", $Default = "False")
ConsoleWrite($oemDriverName & " " & $strNewPortName & " " & $strPrinterName & " " & $strPrinterLocation & " " & $strComment & " " & $Default & @CRLF)
local $cmdLine = "rundll32 printui.dll,PrintUIEntry /if /b " & chr(34) & $strPrinterName & chr(34) & " /r " & chr(34) & $strNewPortName & chr(34) & " /m " & chr(34) & $oemDriverName & chr(34) & " /q "

If StringUpper($Default) = "TRUE" Then
$cmdLine &= " /y "
EndIf
ConsoleWrite (@crlf & $cmdline & @crlf)
_RunDOS ($cmdLine)
if $strComment<>"" and $strComment<>0 then
$cmdline = "rundll32 printui.dll,PrintUIEntry /Xs /n " & chr(34) & $strPrinterName & chr(34) & " comment " & chr(34) & $strComment & chr(34)
ConsoleWrite (@crlf & $cmdline & @crlf)
_RunDOS ($cmdLine)
EndIf
if $strPrinterLocation<>"" and $strPrinterLocation<>0 then
$cmdline = "rundll32 printui.dll,PrintUIEntry /Xs /n " & chr(34) & $strPrinterName & chr(34) & " location " & chr(34) & $strPrinterLocation & chr(34)
ConsoleWrite (@crlf & $cmdline & @crlf)
_RunDOS ($cmdLine)
EndIf
EndFunc ;==>InstallPrinter

Func LoadSettings($XMLFile)
ConsoleWrite($XMLFile & " ")
Local $sFile = $XMLFile
If FileExists($sFile) Then
ConsoleWrite("Found ")
Local $ret = _XMLFileOpen($sFile)
ConsoleWrite($ret & " " & @error & " " & @extended & @CRLF)
If $ret = 0 Then
MsgBox(1 + 48 + 262144, "File Open Error", "Unable to open selected configuration file")
Return 0
EndIf
If _XMLNodeExists("/PrinterGroups/Group") Then
$WindowTitle = _xmlgetattrib("/PrinterGroups", "Name")
ConsoleWrite("PrinterGroups/Group found" & " ")
$AutoInstall = _xmlgetattrib("/PrinterGroups", "AUTO")
Local $GroupCount = _XMLGetNodeCount("/PrinterGroups/Group[*]")
ConsoleWrite($GroupCount & @CRLF)
$z = 0
If $GroupCount > 0 Then
For $X = 1 To $GroupCount
Local $strChild = ""
$GroupName = _xmlgetattrib("/PrinterGroups/Group[" & $X & "]", "Name")
_ArrayAdd($Parent, $GroupName)
$GroupCHK = _xmlgetattrib("/PrinterGroups/Group[" & $X & "]", "Checked")
If StringUpper($GroupCHK) = "TRUE" Then
_ArrayAdd($parentCHK, True)
Else
_ArrayAdd($parentCHK, False)
EndIf
Local $PrinterCount = _XMLGetNodeCount("/PrinterGroups/Group[" & $X & "]/Printer[*]")
For $y = 1 To $PrinterCount
_ArrayAdd($Printers, DllStructCreate($STR))
$z += 1
ConsoleWrite("structureset: " & DllStructSetData($Printers[$z], 1, $GroupName) & @CRLF)
$PrinterName = _xmlgetattrib("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]", "DisplayName")
ConsoleWrite(" DisplayName: " & DllStructSetData($Printers[$z], 2, $PrinterName) & @CRLF)

$DefaultPrinter = _xmlgetattrib("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]", "Default")
ConsoleWrite($DefaultPrinter & @CRLF)
If StringUpper($DefaultPrinter) <> "TRUE" Then $DefaultPrinter = "False"
ConsoleWrite(" Default: " & DllStructSetData($Printers[$z], 18, $DefaultPrinter) & @CRLF)
$Checked = _xmlgetattrib("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]", "Checked")
ConsoleWrite(" Checked: " & DllStructSetData($Printers[$z], 19, $Checked) & @CRLF)
If StringUpper($Checked) = "TRUE" Then
_ArrayAdd($ChildCHK, True)
Else
_ArrayAdd($ChildCHK, False)
EndIf


If $strChild = "" Then
$strChild = $PrinterName
Else
$strChild = $strChild & "|" & $PrinterName
EndIf
$oemDriverName = _xmlgetattrib("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Driver", "OEMName")
ConsoleWrite(" OemName: " & DllStructSetData($Printers[$z], 3, $oemDriverName) & @CRLF)
$SupportedPlatform = _XMLGetFirstValue("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Driver/SupportedPlatform")
ConsoleWrite(" SupportPlatform: " & DllStructSetData($Printers[$z], 4, $SupportedPlatform) & @CRLF)
$Version = _XMLGetFirstValue("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Driver/Version")
ConsoleWrite(" Version: " & DllStructSetData($Printers[$z], 5, $Version) & @CRLF)
$CopyFiles = _xmlgetattrib("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Driver/Location", "CopyFiles")
ConsoleWrite(" CopyFiles: " & DllStructSetData($Printers[$z], 6, $CopyFiles) & @CRLF)
$Source = _XMLGetFirstValue("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Driver/Location/Source")
ConsoleWrite(" Source: " & DllStructSetData($Printers[$z], 7, $Source) & @CRLF)
$Destination = _XMLGetFirstValue("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Driver/Location/Destination")
ConsoleWrite(" Destination: " & DllStructSetData($Printers[$z], 8, $Destination) & @CRLF)
$PortName = _xmlgetattrib("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Port", "Name")
ConsoleWrite(" PortName: " & DllStructSetData($Printers[$z], 9, $PortName) & @CRLF)
$Protocol = _XMLGetFirstValue("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Port/Protocol")
ConsoleWrite(" Protocol: " & DllStructSetData($Printers[$z], 10, $Protocol) & @CRLF)
$HostAddress = _XMLGetFirstValue("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Port/HostAddress")
ConsoleWrite(" HostAddress: " & DllStructSetData($Printers[$z], 11, $HostAddress) & @CRLF)
$PortNumber = _XMLGetFirstValue("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Port/PortNumber")
ConsoleWrite(" PortNumber: " & DllStructSetData($Printers[$z], 12, $PortNumber) & @CRLF)
$SNMPEnabled = _XMLGetFirstValue("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Port/SNMPEnabled")
ConsoleWrite(" SNMPEnabled: " & DllStructSetData($Printers[$z], 13, $SNMPEnabled) & @CRLF)
$UpdateDriver = _XMLGetFirstValue("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Driver/UpdateDriver")
ConsoleWrite(" UpdateDriver: " & DllStructSetData($Printers[$z], 14, $UpdateDriver) & @CRLF)
$INFName = _xmlgetattrib("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Driver", "INFName")
ConsoleWrite(" INF Name: " & DllStructSetData($Printers[$z], 15, $INFName) & @CRLF)
$Location = _XMLGetFirstValue("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Location")
ConsoleWrite(" Location: " & DllStructSetData($Printers[$z], 16, $Location) & @CRLF)
$Comment = _XMLGetFirstValue("/PrinterGroups/Group[" & $X & "]/Printer[" & $y & "]/Comment")
ConsoleWrite(" Comment: " & DllStructSetData($Printers[$z], 17, $Comment) & @CRLF)
Next
ReDim $Child[$X + 1]
$Child[$X] = $strChild
Next
EndIf
EndIf
EndIf
Global $arrNewPorts[UBound($Printers) - 1][5]
Global $arrNewDrivers[UBound($Printers) - 1][8]
Global $arrNewPrinters[UBound($Printers) - 1][6]
For $X = 1 To UBound($Printers) - 1
$arrNewPrinters[$X - 1][0] = DllStructGetData($Printers[$X], 2) ;$PrinterName
$arrNewPrinters[$X - 1][1] = DllStructGetData($Printers[$X], 3) ;$oemDriverName
$arrNewPrinters[$X - 1][2] = DllStructGetData($Printers[$X], 9) ;$PortName
$arrNewPrinters[$X - 1][3] = DllStructGetData($Printers[$X], 16) ;$Location
$arrNewPrinters[$X - 1][4] = DllStructGetData($Printers[$X], 17) ;$comment
$arrNewPrinters[$X - 1][5] = DllStructGetData($Printers[$X], 18) ;$Default

$arrNewDrivers[$X - 1][0] = DllStructGetData($Printers[$X], 3) ;$oemDriverName
$arrNewDrivers[$X - 1][1] = DllStructGetData($Printers[$X], 5) ;version
$arrNewDrivers[$X - 1][2] = DllStructGetData($Printers[$X], 4) ;$SupportedPlatform
$arrNewDrivers[$X - 1][3] = DllStructGetData($Printers[$X], 6) ;$CopyFiles
$arrNewDrivers[$X - 1][4] = DllStructGetData($Printers[$X], 7) ;$Source
$arrNewDrivers[$X - 1][5] = DllStructGetData($Printers[$X], 8) ;$Destination
$arrNewDrivers[$X - 1][6] = DllStructGetData($Printers[$X], 15) ;$INFName
$arrNewDrivers[$X - 1][7] = DllStructGetData($Printers[$X], 14) ;$UpdateDriver

$arrNewPorts[$X - 1][0] = DllStructGetData($Printers[$X], 9) ;$PortName
$arrNewPorts[$X - 1][1] = DllStructGetData($Printers[$X], 10) ;$Protocol
$arrNewPorts[$X - 1][2] = DllStructGetData($Printers[$X], 11) ;$HostAddress
$arrNewPorts[$X - 1][3] = DllStructGetData($Printers[$X], 12) ;$PortNumber
$arrNewPorts[$X - 1][4] = DllStructGetData($Printers[$X], 13) ;$SNMPEnabled

ConsoleWrite("readback: " & $X & @CRLF & " " & DllStructGetData($Printers[$X], 1) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 2) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 3) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 4) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 5) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 6) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 7) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 8) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 9) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 10) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 11) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 12) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 13) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 14) & @CRLF)
ConsoleWrite(" " & DllStructGetData($Printers[$X], 15) & @CRLF)


Next
EndFunc ;==>LoadSettings

Func CheckChilds($nCtrl, $hItem, $nCheck)
While $hItem > 0
$nItem = GetItemID($nCtrl, $hItem)
$arr = GUICtrlRead($nItem, 1)
GUICtrlSetState($nItem, $nCheck * - 3 + $GUI_UNCHECKED)
; Same like: GUICtrlSetState($nItem, BitOr(BitAnd($nCheck, $GUI_UNCHECKED), BitAnd($nCheck, $GUI_CHECKED)))
$hChildItem = GUICtrlSendMsg($nCtrl, $TVM_GETNEXTITEM, $TVGN_CHILD, $hItem)
If $hChildItem > 0 Then CheckChilds($nCtrl, $hChildItem, $nCheck)
$hItem = GUICtrlSendMsg($nCtrl, $TVM_GETNEXTITEM, $TVGN_NEXT, $hItem)
WEnd
EndFunc ;==>CheckChilds

Func GetParents($nCtrl, $hItem, $nCheck)
While $hItem > 0
$hChildItem = GUICtrlSendMsg($nCtrl, $TVM_GETNEXTITEM, $TVGN_CHILD, $hItem)
$nState = $nCheck * - 3 + $GUI_UNCHECKED
$nCheckState = $nState
If $hChildItem > 0 Then GetChilds($nCtrl, $hChildItem, $nCheckState)
$nItem = GetItemID($nCtrl, $hItem)
$arInfo = GUICtrlRead($nItem, 1)
If $nCheckState Then
GUICtrlSetState($nItem, $nState)
Else
GUICtrlSetState($nItem, $GUI_INDETERMINATE)
EndIf
$hItem = GUICtrlSendMsg($nCtrl, $TVM_GETNEXTITEM, $TVGN_PARENT, $hItem)
WEnd
EndFunc ;==>GetParents

Func GetChilds($nCtrl, $hItem, ByRef $nCheck)
While $hItem > 0
$nItem = GetItemID($nCtrl, $hItem)
If Not BitAND(GUICtrlRead($nItem), $nCheck) Then
$nCheck = 0
ExitLoop
EndIf
$hChildItem = GUICtrlSendMsg($nCtrl, $TVM_GETNEXTITEM, $TVGN_CHILD, $hItem)
If $hChildItem > 0 Then GetChilds($nCtrl, $hChildItem, $nCheck)
$hItem = GUICtrlSendMsg($nCtrl, $TVM_GETNEXTITEM, $TVGN_NEXT, $hItem)
WEnd
EndFunc ;==>GetChilds

Func GetItemID($Ctrl, $hItem)
$nID = 0
$hTree = ControlGetHandle("", "", $Ctrl)

$TVITEM = DllStructCreate("uint;int;uint;uint;ptr;int;int;int;int;int")
If @error Then
; DllStructDelete ($TVITEM)
$TVITEM = 0
Return $nID
EndIf
DllStructSetData($TVITEM, 1, $TVIF_PARAM)
DllStructSetData($TVITEM, 2, $hItem)

$nResult = DllCall("user32.dll", "int", "SendMessage", "hwnd", $hTree, "int", $TVM_GETITEM, "int", 0, "ptr", DllStructGetPtr($TVITEM))
If ($nResult[0]) Then
$nID = DllStructGetData($TVITEM, 10)
EndIf

;DllStructDelete($TVITEM)

Return $nID
EndFunc ;==>GetItemID

Func _XMLGetFirstValue($node)
Local $ret_val = _XMLGetValue($node)
If IsArray($ret_val) Then
Return ($ret_val[1])
Else
Return SetError(1, 3, 0)
EndIf
EndFunc ;==>_XMLGetFirstValue

Func InstallAllPrinters()
ConsoleWrite("Install All Printers" & @CRLF)
For $X = 0 To UBound($arrNewPorts) - 1
SplashTextOn ("Instaling All ports", "Installing port " & $x +1 & " of " & UBound($arrNewPorts), 200,100)
InstallNewPort($arrNewPorts[$X][0], $arrNewPorts[$X][1], $arrNewPorts[$X][2], $arrNewPorts[$X][3], $arrNewPorts[$X][4])
Next
For $X = 0 To UBound($Printers) - 1
SplashTextOn ("Instaling All drivers", "Installing driver " & $x +1 & " of " & UBound($Printers), 200,100)
if (Not CheckForDriver(DllStructGetData($Printers[$X], 3))) or (StringUpper(DllStructGetData($Printers[$X], 14)) = "TRUE") Then
InstallDriver(DllStructGetData($Printers[$X], 3), DllStructGetData($Printers[$X], 4), DllStructGetData($Printers[$X], 5), DllStructGetData($Printers[$X], 6), DllStructGetData($Printers[$X], 7), DllStructGetData($Printers[$X], 8), DllStructGetData($Printers[$X], 15))
EndIf
Next
For $X = 0 To UBound($arrNewPrinters) - 1
SplashTextOn ("Instaling All printers", "Installing printer " & $x +1 & " of " & UBound($arrNewPrinters), 200,100)
InstallPrinter($arrNewPrinters[$X][1], $arrNewPrinters[$X][2], $arrNewPrinters[$X][0], $arrNewPrinters[$X][3], $arrNewPrinters[$X][4], $arrNewPrinters[$X][5])
Next
SplashOff()
EndFunc ;==>InstallAllPrinters

Func frmMainWinProc()
While 1

$Msg = GUIGetMsg()
If $Msg <> 0 And $Msg <> -11 Then ConsoleWrite($Msg)
Select
Case $Msg = $GUI_EVENT_CLOSE Or $Msg = $mnuExit
ConsoleWrite("Exit" & @CRLF)
ExitLoop
Case $Msg = $mnuAllPorts
ConsoleWrite("Install All Ports" & @CRLF)
For $X = 0 To UBound($arrNewPorts) - 1
SplashTextOn ("Instaling All ports", "Installing port " & $x +1 & " of " & UBound($arrNewPorts), 200,100)
InstallNewPort($arrNewPorts[$X][0], $arrNewPorts[$X][1], $arrNewPorts[$X][2], $arrNewPorts[$X][3], $arrNewPorts[$X][4])
Next
SplashOff()
Case $Msg = $mnuAllDrivers
ConsoleWrite("Install All Drivers" & @CRLF)
For $X = 0 To UBound($Printers) - 1
SplashTextOn ("Instaling All drivers", "Installing driver " & $x +1 & " of " & UBound($Printers), 200,100)
if (Not CheckForDriver(DllStructGetData($Printers[$X], 3))) or (StringUpper(DllStructGetData($Printers[$X], 14)) = "TRUE") Then
InstallDriver(DllStructGetData($Printers[$X], 3), DllStructGetData($Printers[$X], 4), DllStructGetData($Printers[$X], 5), DllStructGetData($Printers[$X], 6), DllStructGetData($Printers[$X], 7), DllStructGetData($Printers[$X], 8), DllStructGetData($Printers[$X], 15))
EndIf
Next
SplashOff()
Case $Msg = $mnuAllPrinters
InstallAllPrinters()
Case $Msg = $mnuListPorts
ConsoleWrite("List All Ports" & @CRLF)
;_ArrayDisplay ($arrTCPPorts)
_ArrayDisplay($arrTCPPorts, "In use TCP Ports List", -1, 0, "|", "|", "Count|Caption|Protocol|Host Address|Port Number|SNMP Enabled")
Case $Msg = $mnuListDrivers
ConsoleWrite("List All Drivers" & @CRLF)
;_ArrayDisplay ($arrInstalledDrivers)
_ArrayDisplay($arrInstalledDrivers, "In use Drivers List", -1, 0, "|", "|", "Count|Driver Name|Type|Targeted OS")
Case $Msg = $mnuListPrinters
ConsoleWrite("List All Printers" & @CRLF)
;_ArrayDisplay ($arrPrinters)
_ArrayDisplay($arrPrinters, "Installed Printers List", -1, 0, "|", "|", "Count|Name|Port Name|Driver Name|Location")
Case $Msg = $mnuNewPorts
ConsoleWrite("List New Ports" & @CRLF)
;_ArrayDisplay ($arrNewPorts)
_ArrayDisplay($arrNewPorts, "Installed TCP Ports List", -1, 0, "|", "|", "Count|Port Name|Protocol|Host Address|Port Number|SNMP Enabled")
Case $Msg = $mnuNewDrivers
ConsoleWrite("List New Drivers" & @CRLF)
;_ArrayDisplay ($arrNewDrivers)
_ArrayDisplay($arrNewDrivers, "Installed Drivers List", -1, 0, "|", "|", "Count|Driver Name|Targeted OS|Version|Copy Files|Source|Destination|INF Name|Update Driver")
Case $Msg = $mnuNewPrinters
ConsoleWrite("List New Printers" & @CRLF)
;_ArrayDisplay ($arrNewPrinters)
_ArrayDisplay($arrNewPrinters, "Installed Printers List", -1, 0, "|", "|", "Count|Name|Driver Name|Port Name|Location|Comment")
Case $Msg = $mnuAbout
ConsoleWrite("About" & @CRLF)
SplashTextOn("About " & $WindowTitle, "Customizable Printer Installer" & @CRLF & @CRLF & "Author: Isaac Holmes" & @CRLF & @CRLF & "Version: 1.0.0" & @CRLF & @CRLF & "©2010 University of Notre Dame", 250, 200)
Do
$Msg = GUIGetMsg()
Until $Msg = -7
SplashOff()
Case $Msg >= $Tree_Parent_Split[1]
If BitAND(GUICtrlRead($Msg), $GUI_INDETERMINATE) Then ContinueLoop; Do nothing when in indeterminate state
$hItem = GUICtrlSendMsg($TreeView, $TVM_GETNEXTITEM, $TVGN_CARET, 0)
ConsoleWrite($hItem & @CRLF)
If $hItem > 0 Then
$hChildItem = GUICtrlSendMsg($TreeView, $TVM_GETNEXTITEM, $TVGN_CHILD, $hItem)
If $hChildItem > 0 Then CheckChilds($TreeView, $hChildItem, BitAND(GUICtrlRead($Msg), $GUI_CHECKED))
$hParentItem = GUICtrlSendMsg($TreeView, $TVM_GETNEXTITEM, $TVGN_PARENT, $hItem)
If $hParentItem > 0 Then GetParents($TreeView, $hParentItem, BitAND(GUICtrlRead($Msg), $GUI_CHECKED))
EndIf
Case $Msg = $btnInstall
InstallPrinters()
EndSelect
If $fDblClk = True And _GUICtrlTreeView_GetParentHandle($TreeView, _GUICtrlTreeView_GetSelection($TreeView)) <> 0 Then
$fDblClk = False
ConsoleWrite("Double Clicked: " & _GUICtrlTreeView_GetText($TreeView, _GUICtrlTreeView_GetSelection($TreeView)) & " Parent: " & _GUICtrlTreeView_GetParentHandle($TreeView, _GUICtrlTreeView_GetSelection($TreeView)) & _
" My Handle: " & _GUICtrlTreeView_GetItemHandle($TreeView, _GUICtrlTreeView_GetSelection($TreeView)) & " Index: " & $x & @CRLF)
for $x = 1 to ubound($Printers)-1
if DllStructGetData($Printers[$X], 2) = _GUICtrlTreeView_GetText($TreeView, _GUICtrlTreeView_GetSelection($TreeView)) then
MsgBox(262208, _GUICtrlTreeView_GetText($TreeView, _GUICtrlTreeView_GetSelection($TreeView)) & " Information", _
"Printer:" & @CRLF & _
" Install Group: " & DllStructGetData($Printers[$X], 1) & @CRLF & _
" Friendly Name: " & DllStructGetData($Printers[$X], 2) & @CRLF & _
" Location: " & DllStructGetData($Printers[$X], 16) & @CRLF & _
" Comment: " & DllStructGetData($Printers[$X], 17) & @CRLF & _
@CRLF & "Driver:" & @CRLF & _
" Update Driver: " & DllStructGetData($Printers[$X], 14) & @CRLF & _
" INF Name: " & DllStructGetData($Printers[$X], 15) & @CRLF & _
" Printer Driver: " & DllStructGetData($Printers[$X], 3) & @CRLF & _
" Supported Platform: " & DllStructGetData($Printers[$X], 4) & @CRLF & _
" Version: " & DllStructGetData($Printers[$X], 5) & @CRLF & _
" Copy Files: " & DllStructGetData($Printers[$X], 6) & @CRLF & _
" Source: " & DllStructGetData($Printers[$X], 7) & @CRLF & _
" Destination: " & @CRLF & DllStructGetData($Printers[$X], 8) & @CRLF & _
@CRLF & "Port:" & @CRLF & _
" Name: " & DllStructGetData($Printers[$X], 9) & @CRLF & _
" Protocol: " & DllStructGetData($Printers[$X], 10) & @CRLF & _
" Host Address: " & DllStructGetData($Printers[$X], 11) & @CRLF & _
" Port Number: " & DllStructGetData($Printers[$X], 12) & @CRLF & _
" SNMP Enabled: " & DllStructGetData($Printers[$X], 13) & @CRLF)
EndIf
Next
ElseIf $fDblClk = True Then
$fDblClk = False
EndIf
WEnd
EndFunc ;==>frmMainWinProc

Func MY_WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
Local $tNMHDR = DllStructCreate("int;int;int", $lParam)
If @error Then Return
If DllStructGetData($tNMHDR, 3) = $NM_DBLCLK Then $fDblClk = True
$tNMHDR = 0
EndFunc ;==>MY_WM_NOTIFY

Anyone interested in using it but don't want to compile it or find all the include files here is the comiled script along with a sample configuration XML file. This can be used as a standalone program (admin rights or printer install rights required), an SMS/SCCM advertisement or assigned program, or startup script.

Usage:

PrinterInstaller.exe <ConfigFile.xml>

If no config file is specified it will try to load settings from PrinterInstaller.xml as the defualt.

PrinterInstaller.exe

PrinterInstaller.xml

Some additional documentation:

DSS Printer Installer.pdf

Link to comment
Share on other sites


Ok, further digging.

It appears that when run under the System context it does not have permissions to add the printer. My script above returns the same error if I run it manually from a CMD window launched under the System context. The Microsoft provided PRNMNGR.VBS script returns a 80041003 access denied error as does the below vbs script that is the base script for the autoit script and pulled originally from the Scripting Guys. The error is return by the last line.

strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate, (LoadDriver)}!\\" & strComputer & "\root\cimv2")

set objNewPort = objWMIService.get("Win32_TCPIPPrinterPort").SpawnInstance_
Set objPrinter = objWMIService.Get("Win32_Printer").SpawnInstance_
objWMIService.Security_.Privileges.AddAsString "SeLoadDriverPrivilege", True
Set objDriver = objWMIService.Get("Win32_PrinterDriver")

PrinterDriverFriendlyName = "Xerox Global Print Driver PS"

PrinterPortName = "Xrx4050.CC.nd.edu"

DisplayName = "OIT XRX 4050"

'********* Installs Printer Driver ************
objDriver.Name = PrinterDriverFriendlyName
objDriver.SupportedPlatform = "Windows NT x86"
objDriver.Version = "3"
intResult = objDriver.AddPrinterDriver(objDriver)

'********* Installs Printer Port *********
objNewPort.Name = PrinterPortName
objNewPort.Protocol = 1
objNewPort.HostAddress = PrinterPortName
objNewPort.PortNumber = 9100
objNewPort.SNMPEnabled = True
objNewPort.Put_

'********* Install Printer *********

objPrinter.DriverName = PrinterDriverFriendlyName
objPrinter.PortName = PrinterPortName
objPrinter.DeviceID = DisplayName
objPrinter.Location = ""
objPrinter.Network = True
objPrinter.Put_

Link to comment
Share on other sites

Well after apparently stumping the community here and half a day of digging through Google search results it appears the the System account does not have rights when it come to creating a printer via WMI. Ended up changing the printer install section to use rundll32 printui.dll,PrintUIEntry instead and all is working great.

Link to comment
Share on other sites

WMI would work, but you'd have to do some trial and error on impersonate to see what worked and what didn't. However, if you're using SCCM for it (and not using an installation "admin" account to run the script), your current method is probably the easiest to maintain, that is certain ;).

Link to comment
Share on other sites

I played around with impersonate settings and never found any that got it to work.

It amazed me thenumber of posts I found out there of people wanting to do the same kind of thing and the only answer to them was to use startup scripts.

Link to comment
Share on other sites

Well, SCCM really does have trouble with doing certain things as system (which is why a lot of SCCM 2007 functions got away from using the system account in the first place, like previous versions of SMS used to do). Part of the problem of using WMI as system is that WMI has it's own permissions above and beyond local filesystem or registry perms, so proper impersonation is paramount. You probably might have had better luck in using something like psexec to run the command as a real user account.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...