The script goes out to AD and collects all of the printQueue objects in the domain (these represent published printers). From this list the script compiles a list of print servers and dumps all the printer info off each server. The downside to this is that if you have printer servers with no published printers, they'll be missed. This is the data currently collected and outputted to a pipe separated text file:
- Server
- Name
- ShareName
- Comment
- Error
- DriverName
- EnableBIDI
- JobCount
- Location
- PortName
- Published
- Queued
- Shared
- Status
You can easily add more data to this by adding more fields inside the loop. I tested this with some really slow links and Wn2k/Win2k3 servers and it seems to work fine.
In order to use the script, you'll need to provide the FQDN of your domain in the DOMAIN_TO_SEARCH field at the top of the script. Additionally you'll need to optionally modify the FILE_PATH field to change the output destination.
Feel free to leave any suggestions, issues, etc in the comments area below.
'========================================================================== ' NAME: Query AD Printers ' ' AUTHOR: Brian Desmond, brian@briandesmond.com '========================================================================== Option Explicit Const DOMAIN_TO_SEARCH = "dc=sub,dc=domain,dc=com" Const FILE_PATH = "PrinterInventory.txt" Dim fso Set fso = WScript.CreateObject("Scripting.FileSystemObject") Dim PrinterArray Set PrinterArray = WScript.CreateObject("Scripting.Dictionary") ' this way we eliminate dupes ' populate our list of printers Dim cnxn Set cnxn = WScript.CreateObject("ADODB.Connection") cnxn.Provider = "ADsDSOObject" cnxn.Open "Active Directory Provider" Dim cmd Set cmd = WScript.CreateObject("ADODB.Command") cmd.ActiveConnection = cnxn cmd.CommandText = "<LDAP://" & DOMAIN_TO_SEARCH & ">;(&(objectcategory=printQueue)(objectClass=printQueue));serverName;subtree" cmd.Properties("Page Size") = 100 cmd.Properties("Timeout") = 30 cmd.Properties("Cache Results") = False Dim rs Set rs = cmd.Execute While Not rs.eof If Not PrinterArray.Exists(rs.Fields("serverName").Value) Then PrinterArray.Add rs.Fields("serverName").Value, rs.Fields("serverName").Value End If rs.MoveNext Wend rs.close cnxn.Close Dim outputData Set outputData = fso.CreateTextFile(FILE_PATH, True) outputData.WriteLine "Server|Name|ShareName|Comment|Error|DriverName|EnableBIDI|JobCount|Location|PortName|Published|Queued|Shared|Status" Dim wmiSvc Dim wmiItems Dim line Dim serverVersion Dim serverName Dim i For Each i In PrinterArray.Keys If Not Trim(PrinterArray.Item(i)) = "" Then serverName = PrinterArray.Item(i) WScript.Echo "Trying: " & serverName On Error Resume Next serverVersion = CDbl(Left(GetWindowsVersion(serverName), Len(GetWindowsVersion(serverName)) - 5)) Set wmiSvc = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & serverName & "\root\cimv2") Set wmiItems = wmiSvc.ExecQuery("SELECT * FROM Win32_Printer",, 48) If Err.Number <> 0 Then WScript.Echo "Error: " & serverName On Error GoTo 0 Else On Error GoTo 0 Dim printer For Each printer In wmiItems line = "" line = serverName & "|" line = line & printer.Name & "|" line = line & printer.ShareName & "|" If serverVersion > 5.0 Then ' Comment supported on XP & newer If InStr(printer.Comment, VbCrLf) > 0 Then 'scrub bad text line = line & replace(printer.Comment, VbCrLf, " ") & "|" Else line = line & printer.comment & "|" End If Else line = line & "|" End If line = line & GetErrorStateString(printer.DetectedErrorState) & "|" line = line & printer.DriverName & "|" If serverVersion > 5.0 Then ' Comment & enablebidi supported on XP & newer line = line & printer.EnableBIDI & "|" Else line = line & "|" End If line = line & printer.JobCountSinceLastReset & "|" If InStr(printer.location, VbCrLf) > 0 Then 'scrub bad text line = line & Replace(printer.Location, VbCrLf, "") & "|" Else line = line & printer.Location & "|" End If line = line & printer.PortName & "|" If serverVersion > 5.0 Then ' published, queued, shared supported on XP & newer line = line & printer.Published & "|" line = line & printer.Queued & "|" line = line & printer.Shared & "|" Else line = line & "|||" End If line = line & printer.Status outputData.WriteLine line Next End If End If Next outputData.Close Set outputData = Nothing Set fso = Nothing Set wmiItems = Nothing Set wmiSvc = Nothing ' translates Win32_Printer.DetectedErrorState Function GetErrorStateString(errorState) Select Case errorState Case 0 GetErrorStateString = "Unknown" Case 1 GetErrorStateString = "Other" Case 2 GetErrorStateString = "No Error" Case 3 GetErrorStateString = "Low Paper" Case 4 GetErrorStateString = "No Paper" Case 5 GetErrorStateString = "Low Toner" Case 6 GetErrorStateString = "No Toner" Case 7 GetErrorStateString = "Door Open" Case 8 GetErrorStateString = "Jammed" Case 9 GetErrorStateString = "Offline" Case 10 GetErrorStateString = "Service Requested" Case 11 GetErrorStateString = "Output Bin Full" Case Else GetErrorStateString = errorState End Select End Function ' this function returns the windows version Function GetWindowsVersion(server) Dim sbWmiSvc Set sbWmiSvc = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & server & "\root\cimv2") Dim version Dim osInstances Set osInstances = sbWmiSvc.ExecQuery("SELECT * From Win32_OperatingSystem") Dim os For Each os In osInstances version = os.Version Next GetWindowsVersion = version Set sbWmiSvc = Nothing Set osInstances = Nothing Set os = Nothing End Function