Description

I wrote this program to compare the installed printers on multiple citrix servers. (locally installed printers, not redirected) The first time you run the program it will create an INI file in the same directory as your script. (read the directions variables for information) You MUST modify this file to match your environment. You define one print server/client as the “master” and it will compare it to as many others as you want it to. It is matching Printer Name, Port Name, and Driver Name. If they do not exactly match it will show you the difference. It will also tell you if you are missing printers on either of the servers being compared. If you have 3 print servers, lets call them p1, p2 and p3, you could set p1 as the master and p2 and p3 as compare servers. It would compare all installed printers on p1 to p2 and give you the results. It would then compare all printers on p1 to p3 and give you the results.

Source Code

#include <Array.au3>

$configFile = @ScriptDir & "\" & "PrinterCompare.ini"

If FileExists($configFile)Then
	$masterServer = IniRead($configFile, "General", "MasterServer", ".")
	$compareServers = IniRead($configFile, "General", "CompareServers", "")
Else
	IniWrite($configFile,"General", "Directions1", "For MasterServer, type in the name of the computer you will compare all others to. Use a period if you want to use the local computer. Do not use quotes.")
	IniWrite($configFile, "General", "MasterServer", "printserver01")
	IniWrite($configFile,"General", "Directions2", "Separate multiple computers in 'CompareServers' with a Pipe symbol '|', Do not use quotes.")
	IniWrite($configFile, "General", "CompareServers", "printserver02|printserver03")
	MsgBox(0,"","Please setup the configuration file located here: " & $configFile)
	Exit
EndIf



$aCompare = StringSplit($compareServers, "|", 2)

Global $aPrintersMaster
$aPrintersMaster = _GetPrinters($masterServer)

For $compare In $aCompare

	If Not (_ComparePrintes($masterServer, $compare)) Then MsgBox(0,"","Skipping server: " & $compare)
Next



Func _ComparePrintes($masterServer, $compareServer)
	;MsgBox(0,"",$masterServer & " " & $compareServer)
	Local $aPrintersCompare
	$aPrintersCompare = _GetPrinters($compareServer)

	;If we have an issue, skip this computer
	If Not IsArray($aPrintersCompare) Then Return 0

	Global $nomatch = ""
	Local $missingPrinters = "Printers on " & $compareServer & " but not on " & $masterServer & ":" & @CRLF
	Local $missingPrinters2 = "Printers on " & $masterServer & " but not on " & $compareServer & ":" & @CRLF

	For $x = 1 To (UBound($aPrintersCompare, 1) - 1)
		$match = _ArraySearch($aPrintersMaster, $aPrintersCompare[$x][0], 0, 0, 0, 0, 1, 0)
		If $match > 0 Then
			If ($aPrintersMaster[$match][1] <> $aPrintersCompare[$x][1]) Or ($aPrintersMaster[$match][2] <> $aPrintersCompare[$x][2]) Then
				$nomatch &= $masterServer & ": " & $aPrintersMaster[$match][0] & " Driver: " & $aPrintersMaster[$match][1] & " Port: " & $aPrintersMaster[$match][2] & @CRLF
				$nomatch &= $compareServer & ": " & $aPrintersCompare[$x][0] & " Driver: " & $aPrintersCompare[$x][1] & " Port: " & $aPrintersCompare[$x][2] & @CRLF & @CRLF

			EndIf
		Else
			$missingPrinters &= $aPrintersCompare[$x][0] & @CRLF
			;msgbox(0,"","Could not find printer " & $aPrintersCompare[$x][0])
		EndIf

	Next
	For $x = 1 To (UBound($aPrintersMaster, 1) - 1)
		$match = _ArraySearch($aPrintersCompare, $aPrintersMaster[$x][0], 0, 0, 0, 0, 1, 0)
		If $match < 0 Then
			$missingPrinters2 &= $aPrintersMaster[$x][0] & @CRLF
		EndIf
	Next



	_MsgBoxScrollable(0, "Missing Printers", $missingPrinters & @CRLF & @CRLF & $missingPrinters2)

	_MsgBoxScrollable(0, "Printers with different configuration", $nomatch)
	Return 1
EndFunc   ;==>_ComparePrintes



Func _GetPrinters($computer = ".")
	Global $objWMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & $computer & "\root\cimv2")
	If @error Then
		MsgBox(0, "WMI Query Error", "Error connecting to the server " & $computer & ": " & Hex(@error, 8))
		Return 0
	EndIf

	Global $colItems = $objWMIService.ExecQuery("Select * from Win32_Printer")

	Global $result = ""

	Local $aPrinters[1][3]
	$aPrinters[0][0] = 0

	For $objItem In $colItems
		$aPrinters[0][0] += 1
		ReDim $aPrinters[UBound($aPrinters, 1) + 1][3]

		$aPrinters[UBound($aPrinters, 1) - 1][0] = $objItem.Name
		$aPrinters[UBound($aPrinters, 1) - 1][1] = $objItem.DriverName
		$aPrinters[UBound($aPrinters, 1) - 1][2] = $objItem.PortName


	Next
	;MsgBox(0, "Information", $result)
	Return $aPrinters

EndFunc   ;==>_GetPrinters



Func _MsgBoxScrollable($mb_Icon, $mb_Title, $mb_Text, $mb_Time = '')
	;This function is from: http://www.autoitscript.com/forum/topic/48485-how-do-i-make-a-messagebox-scollable/page__hl__msgbox++scroll
	;It was modified slightly to help fix the size of the box
	Local $StrnLenText = LongestStringLen($mb_Text)
	;Msgbox(0,"",$StrnLenText)
	Local $NumberOfLines = (UBound(StringSplit($mb_Text, @CRLF)) - 1) * 6.5
	If (160 + $NumberOfLines) >= @DesktopHeight Then $NumberOfLines = @DesktopHeight - 200
	If $StrnLenText + 150 >= @DesktopWidth - 200 Then $StrnLenText = @DesktopWidth - 200
	Local $Button1Txt = "OK"
	Local $Button2Txt = "Cancel"
	Local $MsgValue = 0
	Local $Timer = ''
	Local $ScrollLabel1 = -1, $ScrollLabel2 = -1
	Local $iMsgBox = GUICreate($mb_Title, $StrnLenText + 150, 100 + $NumberOfLines, -1, -1, 0x00400000, 0x00000008)

	Local $DefaultEditStyle = 0
	If $NumberOfLines >= (@DesktopHeight - 200) Or $StrnLenText + 150 >= 200 Then $DefaultEditStyle = 3150016
	Local $Edit = GUICtrlCreateEdit($mb_Text, 60, 10, $StrnLenText + 80, $NumberOfLines + 30, _
			BitOR($DefaultEditStyle, 64 + 128 + 2048 + 4), 0x990)
	Local $IconID = GUICtrlCreateIcon(@SystemDir & "\User32.dll", $mb_Icon, 10, 10, 35, 35)
	$Button1 = GUICtrlCreateButton($Button1Txt, 10 + ($StrnLenText / 2), 45 + $NumberOfLines, 60 + StringLen($Button1Txt), 25)
	$Button2 = GUICtrlCreateButton($Button2Txt, 80 + ($StrnLenText / 2), 45 + $NumberOfLines, 60 + StringLen($Button2Txt), 25)



	GUISetState()
	If $mb_Time <> 0 Then $Timer = TimerInit()
	ControlFocus($iMsgBox, "", $IconID)

	While 1
		$imsg = GUIGetMsg()
		Select
			Case $imsg = $Button1
				$MsgValue = 6
				ExitLoop
			Case $imsg = $Button2
				$MsgValue = 7
				ExitLoop
			Case $imsg = $ScrollLabel1
				ControlSend($iMsgBox, "", $Edit, "{PgDn}")
				ControlFocus($iMsgBox, "", $IconID)
			Case $imsg = $ScrollLabel2
				ControlSend($iMsgBox, "", $Edit, "{PgUp}")
				ControlFocus($iMsgBox, "", $IconID)
			Case $mb_Time <> 0
				If TimerDiff($Timer) / 1000 >= $mb_Time Then ExitLoop
		EndSelect
	WEnd
	GUIDelete($iMsgBox)
	Return $MsgValue
EndFunc   ;==>_MsgBoxScrollable

Func LongestStringLen($sText)
	;Used by _MsgBoxScrollable()
	Local $BiggestStr = 0
	Local $sSplit = StringSplit($sText, @CRLF)

	For $i = 1 To UBound($sSplit) - 1
		If StringLen($sSplit[$i]) > $BiggestStr Then $BiggestStr = StringLen($sSplit[$i])
	Next

	Return $BiggestStr * 5 + 50
EndFunc   ;==>LongestStringLen

This is great! Thank you. How can it be modified to compare print drivers between servers?

Currently it does compare print drivers on installed printers, but only by the name, not the version number. For example if you have a printer on an HP Laserjet 4 PCL 5e and on a different server it is “HP Laserjet 4 PS” it will notify you.