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