Mattw11486 Posted January 4, 2019 Posted January 4, 2019 Trying to create a tool that helps automate adding printers to machines within our domain. User will provide me with the ip address of the printer, the ip address of their machine - I plug both into the tool, select what type of printer it is, hit the button and it adds the printer to their machine. The problem I am running into is deciding on whether or not to use psexec or powershell to accomplish the remote copying of the drivers to the machine and adding/installing the printer. I feel like psexec is probably the better way to go but I know very little about the commands and how to run it in AutoIT to accomplish my goal. Currently I have it to where it detects if the remote PC is a 32-bit or 64-bit..but from there I want the program to then create a folder in the root of C:\ on the machine, then copy/paste the drivers into that folder. From there, it will then proceed with installation of the printer itself. Any help would be excellent! Current Code: expandcollapse popup#RequireAdmin #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=C:\Program Files (x86)\AutoIt3\Aut2Exe\Icons\SETUP06.ICO #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.14.5 Author: Matt Wood Script Function: Create a Network Printer Object when given the IP Address Delete a selected Network Printer Object #ce ---------------------------------------------------------------------------- #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <Array.au3> #include <PrintMgr.au3> $default = ReadDefault() #Region ### START Koda GUI section ### $Form1 = GUICreate("Printer Tool", 228, 500, 359, 199) $Label2 = GUICtrlCreateLabel("Step 1: Obtain IP Address from Printer. Select which printer type below.", 36, 22, 155, 47) $Radio1 = GUICtrlCreateRadio("Toshiba Printer", 36, 70, 155, 35) GUICtrlSetState(-1, $GUI_CHECKED) $Radio2 = GUICtrlCreateRadio("HP Printer", 36, 100, 155, 35) $Label3 = GUICtrlCreateLabel("Step 2: Enter IP Address/Machine Name of PC you wish to install printer on.", 36, 140, 155, 39) $Input1 = GUICtrlCreateInput("", 38, 184, 155, 21) $Label4 = GUICtrlCreateLabel("Step 3: Enter IP address of Printer.", 36, 220, 155, 47) $Input2 = GUICtrlCreateInput("", 38, 260, 155, 21) $Label5 = GUICtrlCreateLabel("Step 4: Enter name you wish to name printer. If left blank will be set as a default name.", 36, 300, 155, 47) $Input3 = GUICtrlCreateInput("", 38, 350, 155, 21) $Button1 = GUICtrlCreateButton("Add Printer", 48, 400, 131, 49) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### Local $oWMIService = _WMIService() ;Instantiate WMIService Object - Establish Connection If $oWMIService = 0 Then Exit ;If WMI Object failed to instantiate, Abort Script Local $sWMIQueryClass = "Win32_OperatingSystem" ;Declare WMI Class to Query Local $aWMIQueryFields[]= ["OSArchitecture"] ;Declare Fields to Retrieve From WMI Class Func GetPrinterList() Local $arrPrinterList[10];doubt there are more than 20 printers For $i = 1 To 1000 $reg = RegEnumKey("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers", $i) If @error = -1 Then ExitLoop $arrPrinterList[$i] = $reg Next $arrPrinterList[0] = $i -1 ;~ _ArrayDisplay ($arrPrinterList) Return $arrPrinterList EndFunc While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE ExitLoop Case $Button1 $ip=GUICTrlRead($Input1) ;PC name $var=GUICtrlRead($Input2) ;Printer IP $machine=GUICtrlRead($Input3) ;Printer Name _WMIService($ip) $aResults = _WMIQuery($oWMIService,$sWMIQueryClass,$aWMIQueryFields) ;Run WMI Query against WMIService Object If $oWMIService = 0 Then ;Termninate WMIService Object MsgBox("Error","Unable to find Machine","Unable to find this machine") EndIf $results = $aResults[0][1] MsgBox(0,"OSArch",$results) ;Copy Drivers to Remote Machine if GUICtrlRead($Radio1) = 1 And $aResults[0][1] = '64-bit' then $path = @ScriptDir&'\Toshiba\64bit\esf6u.inf_amd64_neutral_b0033b4116535c68\esf6u.inf' EndIf if GUICtrlRead($Radio1) = 1 And $aResults[0][1] = '32-bit' then $path = @ScriptDir&'\Toshiba\32bit\esf3u.inf_x86_neutral_7604b49840b8ec43\esf3u.inf' EndIf if GUICtrlRead($Radio2) = 1 And $aResults[0][1] = '64-bit' then $path = @ScriptDir&'\HP\64bit\hpcu186u.inf' EndIf if GUICtrlRead($Radio2) = 1 And $aResults[0][1] = '32-bit' then $path = @ScriptDir&'\HP\32bit\hpcu186c.inf' EndIf ;Add Printer to Remote Machine $a=StringSplit($ip,".") If $a[0]=4 and GUICtrlRead($Radio1) = 1 Then RunWait(@SystemDir&'\cscript.exe c:\windows\system32\Printing_Admin_Scripts\en-US\prnport.vbs //nologo -a -r "'&$ip&'" -h '&$ip&' -o raw -me -y public -i 1 -n 9100',@SystemDir) RunWait(@SystemDir&'\rundll32.exe printui.dll,PrintUIEntry /if /b "'&$var&'" /f "'&$path&'" /r "'&$ip&'" /m "Toshiba Universal Printer 2"',@SystemDir) MsgBox(0,'Printer Installer','Program Completed. If you entered a valid IP, there will be a "'&$var&'" printer installed in Start > Devices and Printers, right click it to set as default.') $default = ReadDefault() ElseIf $a[0]=4 and GUICtrlRead($Radio2) = 1 Then RunWait(@SystemDir&'\cscript.exe c:\windows\system32\Printing_Admin_Scripts\en-US\prnport.vbs //nologo -a -r "'&$ip&'" -h '&$ip&' -o raw -me -y public -i 1 -n 9100',@SystemDir) RunWait(@SystemDir&'\rundll32.exe printui.dll,PrintUIEntry /if /b "'&$var&'" /f "'&$path&'" /r "'&$ip&'" /m "HP Universal Printing PCL 6"',@SystemDir) MsgBox(0,'Printer Installer','Program Completed. If you entered a valid IP, there will be a "'&$var&'" printer installed in Start > Devices and Printers, right click it to set as default.') $default = ReadDefault() Else MsgBox(16,"Printer Installer","The input you entered does not appear to be an IP Address.") EndIf ;~ Case $Button2 ;~ $var=GUICtrlRead($Combo1) ;~ RunWait(@SystemDir&'\rundll32.exe printui.dll,PrintUIEntry /y /n "'&$var&'"') ;~ sleep(3000) ;~ MsgBox(0,'Printer Default','Program Completed. The '&$var&' has been set as default.') EndSwitch WEnd Exit Func ReadDefault() $arrdefault = GetPrinterList() $combodata = "" for $x = 1 to $arrdefault[0] $combodata = $combodata&$arrdefault[$x]&"|" Next Return($combodata) EndFunc Func _WMIService($sHost = @ComputerName) ;Connect to WMI Service $oWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $sHost & "\root\cimv2") ;Create WMI Service Object If Not IsObj($oWMIService) Then Return SetError(1,0,0) ;If Obj Instantiation Failed, Error Out Return $oWMIService ;Return WMI Service Object EndFunc Func _WMIQuery($oWMIService,$sWMIQueryClass,$aWMIQueryFields) ;Perform WMI Query with Query String and Data Return Parameters If Not IsObj($oWMIService) Then Return SetError(1,0,0) ;If oWMIService is not a valid Object, Error Out If Not IsArray($aWMIQueryFields) Then Return SetError(2,0,0) ;If Query Fields is not a valid array, Error Out Local $aResults = $aWMIQueryFields ;Create Results Array _ArrayColInsert($aResults, 1) ;Add Dimension to Results Array to Hold Query Return Values Local $sWMIQuery = "SELECT " & _ArrayToString($aWMIQueryFields,",") & " FROM " & $sWMIQueryClass ;Create WMI Query String $oItems = $oWMIService.ExecQuery ($sWMIQuery) ;Execute query using WMI Service Object For $i = 0 to UBound($aWMIQueryFields) - 1 ;Loop through WMI Query Results For $oItem In $oItems $aResults[$i][1] = Execute("$oItem." & $aWMIQueryFields[$i]) ;Result Next Next Return $aResults ;Return Result Array EndFunc
caramen Posted January 4, 2019 Posted January 4, 2019 (edited) The best way to Use Psexec. To avoid security issue & syntax fail. Is to use it with domain admin account (From your computer of course). The good thing with that is you wont need to declare an account and password while you run your command. Run without domain account is fail way. Notice that PsExec will only run a file/command on a remote computer and nothing else. One exemple to run a command to update Registry with PsExec : ;(Brackets not needed at all , syntaxt inside brackets not needed if you are domain's admin) C:\Psexec>psexec \\NetworkName,NetworkName,NetworkName (-u "administrator" -p "AdminPassword") -s -i -d regedit.exe /s c:\My.reg Or an other exemple if for exemple you want to run a compiled AutoIT script with PsExec with an other account with domain's rights : net use \\client pwd /user:Domain\DomainAccount copy Software\* \\client\ShareFolder$\temp\ psexec \\client drive:\temp\Software.exe Nice script btw. I learned from you thank you. Edited January 4, 2019 by caramen My video tutorials : ( In construction ) || My Discord : https://discord.gg/S9AnwHw How to Ask Help || UIAutomation From Junkew || WebDriver From Danp2 || And Water's UDFs in the Quote Spoiler Water's UDFs:Active Directory (NEW 2018-10-19 - Version 1.4.10.0) - Download - General Help & Support - Example Scripts - WikiOutlookEX (2018-10-31 - Version 1.3.4.1) - Download - General Help & Support - Example Scripts - WikiExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example ScriptsPowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & SupportExcel - Example Scripts - WikiWord - Wiki Tutorials:ADO - Wiki
Mattw11486 Posted January 4, 2019 Author Posted January 4, 2019 Thanks! For copying the drivers, I think I am going to need to use xcopy but for some reason when running something like runwait(xcopy c:\drivers \\pcname\C$\drivers) causes the program to crash. The same xcopy command works fine within command prompt so I am not sure what I am missing here.
caramen Posted January 5, 2019 Posted January 5, 2019 17 hours ago, Mattw11486 said: causes the program to crash What is the program you are talking about ? My video tutorials : ( In construction ) || My Discord : https://discord.gg/S9AnwHw How to Ask Help || UIAutomation From Junkew || WebDriver From Danp2 || And Water's UDFs in the Quote Spoiler Water's UDFs:Active Directory (NEW 2018-10-19 - Version 1.4.10.0) - Download - General Help & Support - Example Scripts - WikiOutlookEX (2018-10-31 - Version 1.3.4.1) - Download - General Help & Support - Example Scripts - WikiExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example ScriptsPowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & SupportExcel - Example Scripts - WikiWord - Wiki Tutorials:ADO - Wiki
Mattw11486 Posted January 6, 2019 Author Posted January 6, 2019 My program to add the printers remotely but I figured it out. Now I have to figure out how to make the batch file run on the remote computer to add the printer. Almost done!
Subz Posted January 6, 2019 Posted January 6, 2019 Why don't you just add the printer drivers to the print server? You can then add multiple versions of drivers to the share and it will install the appropriate driver? No need to copy drivers manually then.
Mattw11486 Posted January 8, 2019 Author Posted January 8, 2019 Unfortunately, in some of our airports, not all printers are setup on a print server. Most printers at our headquarters are on a print server though. I don't know much about networking and I don't know why it's setup the way it is (I have been told our company plans to move ALL printers to a print server but no ETA given). The reason why I designed this tool though is because in some of our airports, users will reach out to me because they want to install a new printer on 30 machines..this causes a problem because then I have to remote out to each machine, login as my admin account, add the printer, log off and repeat 29 more times. This is why I decided to design this as a way to just add the printers remotely when they provide me the necessary information. I have been working on this all weekend and seem to have it pretty much working flawlessly. It currently only does one machine at a time but I plan to change that to add multiple machines. I will post my final code here for anyone else who may find this useful: expandcollapse popup#RequireAdmin #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=C:\Program Files (x86)\AutoIt3\Aut2Exe\Icons\SETUP06.ICO #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.14.5 Author: Matt Wood Script Function: Create a Network Printer Object when given the IP Address Delete a selected Network Printer Object #ce ---------------------------------------------------------------------------- #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <Array.au3> #include <PrintMgr.au3> $Printfile="printer.bat" FileDelete(@ScriptDir&"\"&$Printfile) $default = ReadDefault() #Region ### START Koda GUI section ### $Form1 = GUICreate("Printer Tool", 228, 500, 359, 199) $Label2 = GUICtrlCreateLabel("Step 1: Obtain IP Address from Printer. Select which printer type below.", 36, 22, 155, 47) $Radio1 = GUICtrlCreateRadio("Toshiba Printer", 36, 70, 155, 35) GUICtrlSetState(-1, $GUI_CHECKED) $Radio2 = GUICtrlCreateRadio("HP Printer", 36, 100, 155, 35) $Label3 = GUICtrlCreateLabel("Step 2: Enter IP Address/Machine Name of PC you wish to install printer on.", 36, 140, 155, 39) $Input1 = GUICtrlCreateInput("", 38, 184, 155, 21) $Label4 = GUICtrlCreateLabel("Step 3: Enter IP address of Printer.", 36, 220, 155, 47) $Input2 = GUICtrlCreateInput("", 38, 260, 155, 21) $Label5 = GUICtrlCreateLabel("Step 4: Enter name you wish to name printer. If left blank will be set as a default name.", 36, 300, 155, 47) $Input3 = GUICtrlCreateInput("", 38, 350, 155, 21) $Button1 = GUICtrlCreateButton("Add Printer", 48, 400, 131, 49) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### Local $oWMIService = _WMIService() ;Instantiate WMIService Object - Establish Connection If $oWMIService = 0 Then Exit ;If WMI Object failed to instantiate, Abort Script Local $sWMIQueryClass = "Win32_OperatingSystem" ;Declare WMI Class to Query Local $aWMIQueryFields[]= ["OSArchitecture"] ;Declare Fields to Retrieve From WMI Class Func GetPrinterList() Local $arrPrinterList[10];doubt there are more than 20 printers For $i = 1 To 1000 $reg = RegEnumKey("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers", $i) If @error = -1 Then ExitLoop $arrPrinterList[$i] = $reg Next $arrPrinterList[0] = $i -1 ;~ _ArrayDisplay ($arrPrinterList) Return $arrPrinterList EndFunc While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE ExitLoop Case $Button1 $ip=GUICTrlRead($Input1) ;PC name $var=GUICtrlRead($Input2) ;Printer IP $machine=GUICtrlRead($Input3) ;Printer Name _WMIService($ip) $aResults = _WMIQuery($oWMIService,$sWMIQueryClass,$aWMIQueryFields) ;Run WMI Query against WMIService Object If $oWMIService = 0 Then ;Termninate WMIService Object MsgBox("Error","Unable to find Machine","Unable to find this machine") EndIf $results = $aResults[0][1] MsgBox(0,"OSArch",$results) ;Copy Drivers to Remote Machine if GUICtrlRead($Radio1) = 1 And $aResults[0][1] = '64-bit' then RunWait("xcopy /e /h /i "&@ScriptDir&"\Toshiba\64bit \\"&$ip&"\C$\drivers\Toshiba\64") $path = 'C:\drivers\Toshiba\64\esf6u.inf' EndIf if GUICtrlRead($Radio1) = 1 And $aResults[0][1] = '32-bit' then RunWait("xcopy /e /h /i "&@ScriptDir&"\Toshiba\32bit \\"&$ip&"\C$\drivers\Toshiba\32") $path = 'C:\drivers\Toshiba\32\esf3u.inf' EndIf if GUICtrlRead($Radio2) = 1 And $aResults[0][1] = '64-bit' then RunWait("xcopy /e /h /i "&@ScriptDir&"\HP\64bit \\"&$ip&"\C$\drivers\HP\64") $path = 'C:\drivers\HP\64\hpcu186u.inf' EndIf if GUICtrlRead($Radio2) = 1 And $aResults[0][1] = '32-bit' then RunWait("xcopy /e /h /i "&@ScriptDir&"\HP\32bit \\"&$ip&"\C$\drivers\HP\32") $path = 'C:\drivers\HP\32\hpcu186c.inf' EndIf ;Add Printer to Remote Machine $a=StringSplit($var,".") $file1=FileOpen(@ScriptDir&'\'&$Printfile,2) If $a[0]=4 and GUICtrlRead($Radio1) = 1 Then FileWriteLine($file1,'cscript.exe c:\windows\system32\Printing_Admin_Scripts\en-US\prnport.vbs //nologo -a -r "'&$var&'" -h '&$var&' -o raw -me -y public -i 1 -n 9100') FileWriteLine($file1,'rundll32.exe printui.dll,PrintUIEntry /if /b "'&$machine&'" /f "'&$path&'" /r "'&$var&'" /m "Toshiba Universal Printer 2"') FileClose($file1) RunWait("xcopy "&@ScriptDir&"\printer.bat \\"&$ip&"\C$\drivers") RunWait("psexec.exe \\"&$ip &" C:\drivers\printer.bat") MsgBox(0,'Printer Installer','Program Completed. If you entered a valid IP, there will be a "'&$machine&'" printer installed in Start > Devices and Printers, right click it to set as default.') $default = ReadDefault() ElseIf $a[0]=4 and GUICtrlRead($Radio2) = 1 Then FileWriteLine($file1,'cscript.exe c:\windows\system32\Printing_Admin_Scripts\en-US\prnport.vbs //nologo -a -r "'&$var&'" -h '&$var&' -o raw -me -y public -i 1 -n 9100') FileWriteLine($file1,'rundll32.exe printui.dll,PrintUIEntry /if /b "'&$machine&'" /f "'&$path&'" /r "'&$var&'" /m "HP Universal Printing PCL 6"') FileClose($file1) RunWait("xcopy "&@ScriptDir&"\printer.bat \\"&$ip&"\C$\drivers") RunWait("psexec.exe \\"&$ip &" C:\drivers\printer.bat") MsgBox(0,'Printer Installer','Program Completed. If you entered a valid IP, there will be a "'&$machine&'" printer installed in Start > Devices and Printers, right click it to set as default.') $default = ReadDefault() Else MsgBox(16,"Printer Installer","The input you entered does not appear to be an IP Address.") EndIf EndSwitch WEnd Func ReadDefault() $arrdefault = GetPrinterList() $combodata = "" for $x = 1 to $arrdefault[0] $combodata = $combodata&$arrdefault[$x]&"|" Next Return($combodata) EndFunc Func _WMIService($sHost = @ComputerName) ;Connect to WMI Service $oWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $sHost & "\root\cimv2") ;Create WMI Service Object If Not IsObj($oWMIService) Then Return SetError(1,0,0) ;If Obj Instantiation Failed, Error Out Return $oWMIService ;Return WMI Service Object EndFunc Func _WMIQuery($oWMIService,$sWMIQueryClass,$aWMIQueryFields) ;Perform WMI Query with Query String and Data Return Parameters If Not IsObj($oWMIService) Then Return SetError(1,0,0) ;If oWMIService is not a valid Object, Error Out If Not IsArray($aWMIQueryFields) Then Return SetError(2,0,0) ;If Query Fields is not a valid array, Error Out Local $aResults = $aWMIQueryFields ;Create Results Array _ArrayColInsert($aResults, 1) ;Add Dimension to Results Array to Hold Query Return Values Local $sWMIQuery = "SELECT " & _ArrayToString($aWMIQueryFields,",") & " FROM " & $sWMIQueryClass ;Create WMI Query String $oItems = $oWMIService.ExecQuery ($sWMIQuery) ;Execute query using WMI Service Object For $i = 0 to UBound($aWMIQueryFields) - 1 ;Loop through WMI Query Results For $oItem In $oItems $aResults[$i][1] = Execute("$oItem." & $aWMIQueryFields[$i]) ;Result Next Next Return $aResults ;Return Result Array EndFunc
caramen Posted January 8, 2019 Posted January 8, 2019 4 hours ago, Mattw11486 said: for anyone else who may find this useful: Yes me, please . My video tutorials : ( In construction ) || My Discord : https://discord.gg/S9AnwHw How to Ask Help || UIAutomation From Junkew || WebDriver From Danp2 || And Water's UDFs in the Quote Spoiler Water's UDFs:Active Directory (NEW 2018-10-19 - Version 1.4.10.0) - Download - General Help & Support - Example Scripts - WikiOutlookEX (2018-10-31 - Version 1.3.4.1) - Download - General Help & Support - Example Scripts - WikiExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example ScriptsPowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & SupportExcel - Example Scripts - WikiWord - Wiki Tutorials:ADO - Wiki
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now