IcemanND Posted August 11, 2010 Posted August 11, 2010 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() EndIfEndFunc ;==>InstallPrinterFinal 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 DeclarationsConst $TVM_GETITEM = $TV_FIRST + 12Global $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"EndIfGlobal $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 $AutoInstallGlobal $WindowTitleGlobal $fDblClkGlobal $structPrinterLocal $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 $ConfigSettingsif $cmdline[0] = 0 then $ConfigSettings = "PrinterInstaller.xml"else $ConfigSettings = $cmdline[1]EndIfLoadSettings($ConfigSettings)$Parent[0] = UBound($Parent) - 1GetInstalledPrinterInfo()Local $Parent_Split = $ParentLocal $btnInstallLocal $mnuFileLocal $mnuExitLocal $mnuPortsLocal $mnuAllPorts, $mnuNewPortsLocal $mnuDriversLocal $mnuAllDrivers, $mnuNewDriversLocal $mnuPrintersLocal $mnuAllPrinters, $mnuNewPrintersLocal $mnuHelpLocal $mnuAbout#EndRegion Declarations#Region MAINGlobal $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 = 0For $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) NextNextIf StringUpper($AutoInstall) = "TRUE" Then InstallPrinters() Exit (0)EndIfGUISetState()GUIRegisterMsg($WM_NOTIFY, "MY_WM_NOTIFY")frmMainWinProc()GUIRegisterMsg($WM_NOTIFY, "")#EndRegion MAINFunc 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 ;==>InstallPrintersFunc 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 EndIfEndFunc ;==>CheckForDriverFunc 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] NextEndFunc ;==>GetInstalledPrinterInfoFunc 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 ;==>InstallNewPortFunc 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 ;==>InstallDriverFunc 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) EndIfEndFunc ;==>InstallPrinterFunc 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) NextEndFunc ;==>LoadSettingsFunc 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) WEndEndFunc ;==>CheckChildsFunc 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) WEndEndFunc ;==>GetParentsFunc 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) WEndEndFunc ;==>GetChildsFunc 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 $nIDEndFunc ;==>GetItemIDFunc _XMLGetFirstValue($node) Local $ret_val = _XMLGetValue($node) If IsArray($ret_val) Then Return ($ret_val[1]) Else Return SetError(1, 3, 0) EndIfEndFunc ;==>_XMLGetFirstValueFunc 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 ;==>InstallAllPrintersFunc 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 WEndEndFunc ;==>frmMainWinProcFunc 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 = 0EndFunc ;==>MY_WM_NOTIFYAnyone 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.exePrinterInstaller.xmlSome additional documentation:DSS Printer Installer.pdf
IcemanND Posted August 11, 2010 Author Posted August 11, 2010 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", TrueSet 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 = PrinterDriverFriendlyNameobjDriver.SupportedPlatform = "Windows NT x86"objDriver.Version = "3"intResult = objDriver.AddPrinterDriver(objDriver)'********* Installs Printer Port *********objNewPort.Name = PrinterPortNameobjNewPort.Protocol = 1objNewPort.HostAddress = PrinterPortNameobjNewPort.PortNumber = 9100objNewPort.SNMPEnabled = TrueobjNewPort.Put_'********* Install Printer *********objPrinter.DriverName = PrinterDriverFriendlyNameobjPrinter.PortName = PrinterPortNameobjPrinter.DeviceID = DisplayNameobjPrinter.Location = ""objPrinter.Network = TrueobjPrinter.Put_
IcemanND Posted August 14, 2010 Author Posted August 14, 2010 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.
cluberti Posted August 15, 2010 Posted August 15, 2010 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 .
IcemanND Posted August 15, 2010 Author Posted August 15, 2010 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.
cluberti Posted August 15, 2010 Posted August 15, 2010 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.
IcemanND Posted August 15, 2010 Author Posted August 15, 2010 Due to security restrictions I wouldn't have been able to use psexec. It would have been easier to allow standard users to be able to install printers but I couldn't do that either.
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now