Showing posts with label Batch. Show all posts
Showing posts with label Batch. Show all posts

Saturday, July 2, 2016

PowerShell: Using DNS and Printer CSV List for IP-Based Printer Installs on Random Network Environments

I support incident management teams and have been trying to find a simple-ish way to have users install printers no matter our network environment.  I setup the same server every incident so that is where I place all scripts and drivers.  We perform massive printing in a short amount of time and this can cause printers to be replaced as they wear out.  Instead of visiting every networked laptop to update printers, I now have 10 static printer numbers and use a CSV file to give driver information, IP address, and printer name.  The user locates the nearest printer, double-clicks the installation batch file, and the process removes the old driver and IP address of that printer and installs the current settings.  This process has been tested for PowerShell version 4.0.
Steps in creating this printer installation process:
  1. Remote into each printer and setup a DNS name.  Ping the IP and DNS name after making the change.  Ensure you allow the printer to take the DNS suffix of the local DHCP server.  Use DHCP.
  2. Download and test the driver that'll be used.  Find the correct INF file that has the printer driver name.  You'll have to add the printer driver name and driver shared folder location to the printerlist.csv file.
  3. Label your printers so users know which printer they need to install.
  4. Create your batch files which start the install process:

@CLS
@powershell -command "start-process powershell" -verb runas -argumentlist '-ExecutionPolicy bypass -file \\server\printers\InstallPrinter.ps1 Team12P1'
    • @cls clears screen to get rid of extraneous messages while starting script
    • @powershell -command "start-process powershell" -verb runas elevates PowerShell to runas Administrator and bypass the UAC settings which can sometimes stop driver installations
    • -argumentlist '-ExecutionPolicy bypass -file \\server\printers\InstallPrinter.ps1 Team12P1' bypasses any PS script execution policy setting that may be set on that computer.  Then it runs the InstallPrinter.ps1 script and passes the Team12P1 variable to that script so it can look up the printer in the CSV file. Create separate batch files for each printer and change the variable to the DNS name of that printer.
    1. Create and input printer information into the printerlist.csv file.  Here is a sample:

    DNSName,DriverShare,DriverINF,DriverName,LastKnownIP,MakeModel,Supplies,Notes
    Team12P1,\\Team12server\printers\Drivers\HPOJP8630,hpvyt13.inf,HP Officejet Pro 8630,192.168.1.100,HPOJP8630,951XL,
    Team12P2,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,192.168.1.100,HPLJP400MFP,80X,
    Team12P3,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,192.168.1.100,HPLJP400MFP,80X,
    Team12P4,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,192.168.1.100,HPLJP400MFP,80X,
    Team12P5,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,192.168.1.100,HPLJP4015,64A,
    Team12P6,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,192.168.1.100,HPLJP4015,64A,
    Team12P7,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,192.168.1.100,HPLJ600,90A,
    Team12P8,\\Team12server\printers\Drivers\HPOJP8630,hpvyt13.inf,HP Officejet Pro 8630,192.168.1.100,HPOJP8630,951XL,
    ,,,,,,,
    Team12P10,\\Team12server\Printers\Drivers\HPCLJ5520,hpc5520u.inf,HP Color LaserJet CP5520 Series PCL 6,192.168.1.100,HPCLJ5525,650A,USB and WiFi Only
    Team12L1,\\Team12server\printers\Drivers\HPUniversalPCL5,hpcu180t.inf,HP Universal Printing PCL 5,,HPLJ1102W,85A,
    Team12L2,,,,,EpsonWF3640,Epson252XL(BCYM),Ordering Manager
    
    • DNSName: Printer name DNS will use to search for an IP
    • DriverShare: Printer driver UNC folder location
    • DriverINF: Printer driver INF file located at the DriverShare location
    • DriverName: Exact printer name found within the Driver INF file
    • LastKnownIP: Static IP used to create a port when the printer and laptop are on different networks. You will have to create a new IP Port when the laptop is on the same network as the printer.
    • MakeModel: Not used in scripts but for your reference
    • Supplies: Not used in scripts but place to note what print cartridges each printer needs
    • Notes: Not used in scripts but provides general information
    1. Create the InstallPrinter.ps1 file referenced in the initial printer installation batch file.  Here is the script I use:

    #No 32-bit support
    $DNSName = $args
    $printerlist = import-csv \\server\printers\installscripts\printerlist.csv|? DNSName -eq $DNSName
    $DriverShare = $printerlist.drivershare
    $DriverINF = $printerlist.driverinf
    $DriverName = $printerlist.drivername
    $LastKnownIP = $printerlist.lastknownIP
    $IP = $LastKnownIP
    
    #Checking for old version of printer, then deleting it so new version can be added
    if ((gwmi win32_service|? name -match spool|select -expand state) -eq 'Stopped'){start-service spooler}
    if ((gwmi win32_printer|select -expand name) -contains $DNSName){
    #This will remove any spooled jobs then delete the printer with the old IP address
    if ((gwmi win32_service|? name -match spool|select -expand state) -eq 'running'){stop-service spooler}
    remove-item c:\windows\system32\spool\printers\*.* -force
    do {sleep 1}until((gwmi win32_service|? name -match spool|select -expand state) -eq 'Stopped')
    start-service spooler
    sleep 5
    $settings = gwmi win32_printer|? name -eq $DNSName|select *
    write-host "`nDeleting old printer installation`n"
    cscript c:\windows\system32\printing_admin_scripts\en-us\prnmngr.vbs -d -p $DNSName
    $Oldport = $settings.portname
    write-host "`nDeleting old Port: $Oldport`n" -f blue
    $portmsg = cscript c:\windows\system32\printing_admin_scripts\en-us\prnport.vbs -d -r $Oldport
    $d = cscript c:\windows\system32\printing_admin_scripts\en-us\prndrvr.vbs -x
    }
    
    write-host ("Printer: " + $DNSName)-f green
    if ($IP.count -gt 0){write-host ("IP address: " + $IP)-f green}else{write-host ("No Active IP, using last known IP: " + $IP)-f red}
    write-host ("`n$DNSName will be available once this window disappears (approx. 3 minutes).`n") -f yellow
    $delprinters = cscript c:\windows\system32\printing_admin_scripts\en-us\prndrvr.vbs -x
    cscript c:\windows\system32\printing_admin_scripts\en-us\prndrvr.vbs -a -m $DriverName -h $DriverShare -i ($DriverShare + "\" + $DriverINF)
    cscript c:\windows\system32\printing_admin_scripts\en-us\prnport.vbs -a -r $IP -h $IP -o raw -n 9100
    #rundll32 printui.dll,PrintUIEntry /if /b $DNSName /r $IP /m $DriverName
    cscript c:\windows\system32\printing_admin_scripts\en-us\prnmngr.vbs -a -p $DNSName -m $DriverName -r $IP
    if ((gwmi win32_printer|select -expand name) -contains $DNSName){write-host "`n$DNSName installed correctly!" -f green;sleep 5}
    

    Now you have a generic printer installation process that you can easily alter when you need to update IPs, Printer Names, or Printer Driver information.  As long as you've renamed your printers DNS names correctly, they should be found on any network subnet you share.  Also, the printerlist.csv file is easy to load into Excel and use for other things besides your installation scripts.

    Last note: In my scenario, I have this system connected to a Box account so all changes are backed up to the cloud and I can update these files from the cloud outside the local subnet/network.

    Monday, November 25, 2013

    CMD: Install Windows 7 IP-based Printers via batch file

    IT Departments debate over Server-based and IP-based direct printing.  I use IP-based printing as a way to lower WAN traffic, negate at least two points of failure, and speedup user response/print time.  Microsoft has developed some fine printer scripts they introduced in Windows XP.  They further polished these scripts in Windows 7 and placed them into their own printing_admin_scripts subfolder.  I'm sharing my sample script and giving a quick explanation of each command.  For more details about the Microsoft VB script switches, visit Microsoft's TechNet site or use Notepad to read the syntax notes placed inside each VBS file.

    REMARK                   --- Start of Script ---

    REMARK Added a script title so I know what printer I'm installing

    echo *** Installing Canon iPF720 Plotter ***

    REMARK Remove old printer presence via PowerShell registry search

    PowerShell "if (test-path 'hklm:\software\microsoft\windows NT\currentversion\Print\Printers\HP DesignJet 1050C Plotter'){cscript c:\windows\system32\printing_admin_scripts\en-us\prnmngr.vbs -d -p 'HP DesignJet 1050C Plotter'}"

    REMARK Checking for processor type then installing appropriate driver
    REMARK AMD64 works with all typical Windows useable 64-bit processors

    if %processor_architecture% equ AMD64 (cscript c:\windows\system32\printing_admin_scripts\en-us\prndrvr.vbs -a -m "Canon iPF720" -h "\\server\share\Printers\Drivers\Canon iPF720\64-bit\Driver" -i "\\server\share\Printers\Drivers\Canon iPF720\64-bit\Driver\6WJF02M.INF") else (cscript c:\windows\system32\printing_admin_scripts\en-us\prndrvr.vbs -a -m "Canon iPF720" -h "\\server\share\printers\Drivers\Canon iPF720\Driver" -i "\\server\share\printers\Drivers\Canon iPF720\Driver\2WJF02M.INF")

    REMARK Adding the IP port the new printer will use

    cscript c:\windows\system32\printing_admin_scripts\en-us\prnport.vbs -a -r "CanoniPF720" -h 192.168.1.100 -o raw -n 9100

    REMARK Putting the Friendly name, driver, and port together

    cscript c:\windows\system32\printing_admin_scripts\en-us\prnmngr.vbs -a -p "Canon iPF720 Plotter" -m "Canon iPF720" -r "CanoniPF720" 

    REMARK Added a 10 second pause so I can chain install scripts together yet still monitor each installation progress

    timeout /t 10

    REMARK                   --- End of Script ---

    I also thought about adding an audible prompt when things go right or wrong.  This would lessen the need to physically watch the install but rather allow multitasking by listening out for the correct sounds after each install while performing other duties.

    Friday, February 8, 2013

    PowerShell: Passing PS Variables to Batch Files

    I couldn't find many easy ways to transfer variables from PowerShell to cmd.exe batch files so I came up with my own solution.  We delete the old temp variable holding file, use PowerShell to create the variable and write the output to a go-between batch file, call that go-between batch file from your original batch file, and use the transferred variable.  Let me know if you don't get it, have questions, or have better suggestions:

    1. Delete the variable-holding batch file from the last time it was used:
    If exist d:\computername.bat del d:\computername.bat >nul

    2.  From your batch file, create your PowerShell variable (I wanted to pick up the computer name):

    powershell "$ComputerName = ('HQ-' + (gwmi win32_systemenclosure).SMBIOSAssetTag);write ('set PC=' + $computername)|out-file d:\computername.bat -encoding ASCII"

    Note: In your new computername.bat file you have:
    Set PC=HQ-R0xxxx
    Which is a valid DOS batch command to create a variable named PC.

    3. By writing the results into a batch file (computername.bat), you can call the new batch file from your original one.  Also, by writing a batch command to set a DOS variable, you've now transferred your PowerShell variable to a batch file.  From your original script:
    call d:\computername.bat

    4.  Now you can use the %PC% variable in your DOS batch file without having to load PowerShell each time you want to pull up the variable.  Obviously you can create all your variables from one PowerShell instance and have the command write out all the Set commands.

    Also note, most systems have a restrictive PowerShell script execution policy so writing PS one-liners makes them easier to run since you don't have to worry about the script policy.

    Example Batch File:


    @Echo Off
    if exist d:\computername.bat del d:\computername.bat >nul
    PowerShell "$ComputerName = ('HQ-' + (gwmi win32_systemenclosure).SMBIOSAssetTag);write ('set PC=' + $computername)|out-file d:\computername.bat -encoding ASCII"
    call d:\computername.bat
    :InstallImage
    cls
    Echo.
    Echo                               MAIN IMAGING MENU (%PC%)
    Echo.
    ...