ICC Home  /  Members  /  Meetings  /  Peer Support  /  Documentation  /  Projects


The Printers.vbs script            


Return to IT/SA Services Documentation: Active Directory

Overview

This script was updated by Andrew Carey in mid-December of 2009. It had
always handled installing new printers for users, but it was updated to
remove references for printers to which a user no longer has access. The
code also was changed to accept the print server name as an argument;
this will allow it to serve remotes sites as well as those on campus
which are served by if-srv-print. Finally, Andrew added "debug" option
so the script can be run from the command-line to help diagnose problems
(see here for details).

The code

Andrew actually added some comments! The "intDebugMode" variable controls
whether the script outputs various diagnostic information at numerous
locations throughout the code.


'***IFAS Printer Mapping Script
'***Last Modified: December 10, 2009
'***By: Andrew Carey (agcarey@ufl.edu)
'***Normal Syntax: cscript printers.vbs Print_Server_Name
'***Example: printers.vbs if-srv-print
'***Debug Mode Syntax: cscript printers.vbs Print_Server_Name /debug
'***Example: printers.vbs if-srv-print /debug
'***Debug mode will run the script and output status messages, and          

On Error Resume Next
'initialize DebugMode to 0 (off)
intDebugMode = 0

If a print server name was not passed in, the script exits with an error
message. This is also where the code checks if it should be running in
debug mode and sets "intDebugMode" accordingly.


'Perform an action depending on the number of arguments entered on the command line
Select Case Wscript.Arguments.Count
	'With zero arguments, the print server name has not been specified so the script will display an error message and exit
	Case 0
		Wscript.echo "Incorrect Syntax: Print server name is required."
		Wscript.echo ""
		Wscript.echo "Example: printers.vbs if-srv-print"
		Wscript.echo "or"
		Wscript.echo "Example: printers.vbs if-srv-print /debug"
		Wscript.echo "To run the script with debugging information output to the screen"
		Wscript.quit
	'If one argument is given, set it as the print server name
	Case 1
		strPrintServer = Wscript.Arguments(0)
	'With two arguments, set the print server name to the first argument, and check the second argument
	'To determine if the user wants to run the script in debug mode
	Case 2
		strPrintServer = Wscript.Arguments(0)
		If strcomp(lcase(Wscript.Arguments(1)), "/debug") = 0 Then
			intDebugMode = 1
		End If
	'if there are more than two arguments, assume the user has made an error, display an error message and exit.	
	Case Else
		Wscript.echo "Incorrect Syntax: Too many arguments"
		Wscript.echo ""
		Wscript.echo "This script onlt accepts two arguments - the print server name and the /debug flag"
		Wscript.echo "Example: printers.vbs if-srv-print"
		Wscript.echo "or"
		Wscript.echo "Example: printers.vbs if-srv-print /debug"
		Wscript.echo "To run the script with debugging information output to the screen"
		Wscript.quit
	End Select

	
'***********Start DebugMode Code*****************
if intDebugMode = 1 then
	wscript.echo (now) & " - Starting printer script"
	wscript.echo "Waiting 10 seconds, this is normal"
	wscript.echo ""
end if
'***********End DebugMode Code*******************

'sleep for 10 seconds
wscript.sleep 10000

Various objects are created for providing information about the user and
the machine to which they are logging on.


Const ADS_SCOPE_SUBTREE = 2
Set objNetwork = CreateObject("WScript.Network")
Set objConnection = CreateObject("ADODB.Connection")
Set objDNCommand =   CreateObject("ADODB.Command")
Set objPrintQueueCommand =   CreateObject("ADODB.Command")
objConnection.Open "Provider=ADsDSOObject;"

There are several printers which are widely shared (for public labs) but
which are hidden within UFAD so they aren't installed for everyone by this
script. Those printers are generally installed via a loopback GPO on the
computers in the corresponding labs. The script notes these (exempts them
from deletion) so as to not remove them if they are already installed.


'Printers which will not be deleted from computers (mostly used in labs)
PrintersExemptFromDeletion = "EYN-hp4300pcl6, EYN-hp4300ps, agr-hpbi1200"

The script then retrieves the username of the person logging on as well as
the computername of the computer they are logging onto.


'Get the user's username and computername
strUsername =  objNetwork.UserName 
strComputername = objNetwork.ComputerName

'***********Start DebugMode Code*****************
if intDebugMode = 1 then
	Wscript.echo "Username: " & strUsername
	Wscript.echo "Computer name: " & strComputername
	Wscript.echo "Print Server: " & strPrintServer
	Wscript.echo "Printers Exempt From Deletion: " & PrintersExemptFromDeletion
	wscript.echo ""
end if
'***********End DebugMode Code*******************

The script makes sure the script won't be run on the print server itself!


'Make sure the script is not being run on the print server
if strcomp(lcase(strComputername), lcase(strPrintServer)) = 0 then 
	wscript.echo "This script should not be run on the print server.  Please run this script from client computers only"
	wscript.quit
end if

The script then pings the print server for availability; that ensures mapped
printers are not deleted due to network or server problems and the script
quickly exits if the server is not reachable.


'make sure that the print server is available (responding to pings)
'this ensures that mapped printers are not deleted due to network or server problems
set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery _
      ("select * from Win32_PingStatus where address = '" & strPrintServer & "'")

 for each objRetStatus in objPing
    if IsNull(objRetStatus.StatusCode) or objRetStatus.StatusCode<>0 then

	'***********Start DebugMode Code*****************
		if intDebugMode = 1 then
			WScript.Echo strPrintServer &" is not available"
		end if
	'***********End DebugMode Code*******************	
	 
	wscript.quit

	Else
	
	'***********Start DebugMode Code*****************
		if intDebugMode = 1 then
			wscript.echo strPrintServer & " is available"
		end if
	'***********End DebugMode Code*******************	

	end if
next

A query is made to UFAD to determine the list of available printers
(i.e., printer queue objects associated with the print server). The list
built only includes those printer objects to which the user has read
access.


'Search for the Distinguished Name of the print server 
Set objDNCommand.ActiveConnection = objConnection
objDNCommand.Properties("Page Size") = 1000
objDNCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 

objDNCommand.CommandText = _
    "SELECT distinguishedName FROM 'LDAP://dc=ad,dc=ufl,dc=edu' WHERE objectCategory='computer' " & _
        "AND CN='" & strPrintServer & "'"
Set objDNRecordSet = objDNCommand.Execute
objDNRecordSet.MoveFirst
strPrintServerDn = objDNRecordSet.Fields("distinguishedName").Value

'***********Start DebugMode Code*****************
if intDebugMode = 1 then
	wscript.echo strPrintServer & " Distinguished Name: " & strPrintServerDN
	wscript.echo ""
	wscript.echo (now) & " - Enumerating Printers on " & strPrintServer
end if
'***********End DebugMode Code*******************

'Enumerates printers on print server
Set objPrintQueueCommand.ActiveConnection = objConnection
objPrintQueueCommand.CommandText = "Select printShareName from 'LDAP://" & strPrintServerDN & "' where objectClass='printQueue'" 
objPrintQueueCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
objPrintQueueCommand.Properties("Cache Results") = False 
Set objPrintQueueRecordSet = objPrintQueueCommand.Execute

Next a WMI query is made on the computer itself to get the list of local
printers currently available.


'***********Start DebugMode Code*****************
if intDebugMode = 1 then
	wscript.echo (now) & " - Done Enumerating Printers on "& strPrintServer
	Wscript.echo (now) & " - Enumerating Printers on local machine"
end if
'***********End DebugMode Code*****************

'Enumerates printers on local machine and removes erroneous printers
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colPrinters = objWMIService.ExecQuery ("Select ShareName, ServerName, Name, Attributes from Win32_Printer")

'***********Start DebugMode Code*****************
if intDebugMode = 1 then
	Wscript.echo (now) & " - Done Enumerating Printers on local machine"
end if
'***********End DebugMode Code*****************

This complicated section examines each of the printers on the local machine
one-at-a-time in a large loop in order to decide if they should stay or go.
The script first checks to see if the local printer references an obsolete
server ("if-srv-file1, "nt-file" or "if-wec-srv"); if so it is deleted. If
instead the local printer references the proper print server it is either
marked as valid because it is on the exemption list or the script matches
it (within another loop) against the list of available printers on the
server. If a match is found, the printer is marked as valid. At the end of
the matching, any invalid printers are removed. Local printers not
referencing the print server are left alone as well.


'For each local Printer 
For each objPrinter in colPrinters
	If objPrinter.ShareName <> "" then
		'Check if the local printer points to an old server and delete
		If lcase(objPrinter.ServerName) = "\\if-srv-file01" or lcase(objPrinter.ServerName) = "\\nt-file" or lcase(objPrinter.ServerName) = "\\if-wec-srv" then
			objPrinter.Delete_
		End if
		
		'Check that the local printer is on the print server
		if lcase(objPrinter.ServerName) = "\\"& strPrintServer then
			curLocalPrinter = objprinter.servername & "\" & objprinter.sharename

		'***********Start DebugMode Code*****************
			if intDebugMode = 1 then
				Wscript.echo ""
				wscript.echo "Local Printer: " &curLocalPrinter
				wscript.echo "Printer is on " & strprintserver		
			end if
		'***********End DebugMode Code*******************
		
			'reset valid printer to 0 
			'all printers start out as erroneous and need to be checked before they are cnsidered valid
			ValidPrinter = 0
			
			'check if the printer is in the exemption list (exempt from deletion)
			'and set the printer as valid if it is on the exemption list
			if InStr(lcase(PrintersExemptFromDeletion), lcase(objprinter.sharename)) > 0 then
				ValidPrinter = 1
				
			'***********Start DebugMode Code*****************
				if intDebugMode = 1 then
					wscript.echo "Printer is in the exemptionlist"
				end if
			'***********End DebugMode Code*******************
										
			elseIf objPrintQueueRecordSet.EOF = False then
				objPrintQueueRecordSet.MoveFirst
				
				'Loop through each remote printer and compare it against the current local printer to determine if the local printer is valid
				'The loop will exit when the local printer is found to be valid or it has been checked against all remote printers and found to be invalid
				Do Until objPrintQueueRecordSet.EOF OR ValidPrinter = 1
					printShareName = objPrintQueueRecordSet.Fields("printShareName").Value
					curRemotePrinter= "\\" & strPrintServer & "\" & printShareName(0)
				
				'***********Start DebugMode Code*****************
					if intDebugMode = 1 then
						wscript.echo "Remote Printer: " & curRemotePrinter
					end if
				'***********End DebugMode Code*******************	
					
					'compare the current local printer against the current remote printer
					PrinterComp =(strcomp(lcase(curLocalPrinter), lcase(CurRemotePrinter)))
					
					'if the current local printer matches the current remote printer, then the local printer is not erroneous (is valid).
					If (PrinterComp = 0) Then	
						ValidPrinter = 1
					
					'***********Start DebugMode Code*****************
						if intDebugMode = 1 then
							wscript.echo "** Printer match, user has permission **"
						end if
					'***********End DebugMode Code*******************
					
					else 
					'move to the next remote printer in the list
					objPrintQueueRecordSet.MoveNext
					end if
		
				Loop
			End If
			
			'if the local printer does not have a match in the remote printer list
			If ValidPrinter = 0 Then
				'The user no longer has permission to the remote printer, so delete it fom the local computer
				objprinter.delete_
			end if
			'move to the first remote printer in preparation for checking the next local printer	
			objPrintQueueRecordSet.MoveFirst 
			
		'If the printer is not on the print server, ignore it	
		else 
		'***********Start DebugMode Code*****************		
			if intDebugMode = 1 then
				wscript.echo ""
				wscript.echo "Local Printer: " & objprinter.servername & "\" & objprinter.sharename
				wscript.echo "Printer is not on "& strPrintServer
			end if
		'***********End DebugMode Code*******************
		end if
	End If
'move to the next local printer	
Next

This final section installs printers which are available to the user on the print server.


'***********Start DebugMode Code*****************
if intDebugMode = 1 then
	wscript.echo ""
	wscript.echo (now) & " - Install printers"
end if
'***********End DebugMode Code*******************

'Installs printers not already installed
objPrintQueueRecordSet.MoveFirst
If objPrintQueueRecordSet.EOF = FALSE then
	objPrintQueueRecordSet.MoveFirst
	Do Until objPrintQueueRecordSet.EOF
		printShareName = objPrintQueueRecordSet.Fields("printShareName").Value

	'***********Start DebugMode Code*****************
		if intDebugMode = 1 then
			wscript.echo lcase("\\"& strPrintServer & "\" & printShareName(0))
		end if
	'***********End DebugMode Code*******************
	
		objNetwork.AddWindowsPrinterConnection "\\" & strPrintServer & "\" & printShareName(0)
		objPrintQueueRecordSet.MoveNext
	Loop
End If

'***********Start DebugMode Code*****************
if intDebugMode = 1 then
	wscript.echo ""
	wscript.echo (now) & " - Printer script completed"
end if
'***********End DebugMode Code*******************

last edited 17 December 2009 by Steve Lasley