About your current scenario, you could try to set two policies:
- Use Universal printing only
- Do not auto-create client printers
then force the update of the group policy (client side).
Maybe you want that client and server printers mirror each other, but just for testing.
(Note, however, that I've seen much worse than 15 seconds in WMI enumerations in different situations. Note also that I'm no expert in Citrix Sessions/UPS.)
Querying with WQLWQL (SQL for WMI) Keywords
EnumerationOptions.Rewindable Property
Use the Like Operator to Simplify Your WQL Queries_Query.Condition = "NOT DeviceID LIKE '%fax%' AND NOT DeviceID LIKE '%xps%' AND NOT DeviceID LIKE '%PDF%'"
QUERY MIN MAX
One Printer: 96ms - 181ms
All Printers: (7) 107ms - 190ms
Filtered: (4) 108ms - 229ms
50 iterations measured using a StopWatch
Dim _SW As Stopwatch = Stopwatch.StartNew()
Dim _Printers As List(Of Printer) = GetSystemPrinters()
Console.WriteLine(_SW.ElapsedMilliseconds.ToString())
This is the code and object used:
Public Function GetSystemPrinters() As List(Of Printer)
Dim _Printers As New List(Of Printer)()
Dim _ConnOptions As New ConnectionOptions()
_ConnOptions.Authentication = AuthenticationLevel.Connect
_ConnOptions.Impersonation = ImpersonationLevel.Impersonate
'If needed => .UserName, .Password, .Authority
_ConnOptions.Timeout = EnumerationOptions.InfiniteTimeout
Dim _Scope As New ManagementScope("\\" + Environment.MachineName + "\root\CIMV2", _ConnOptions)
_Scope.Connect()
Dim _Query As New SelectQuery("SELECT * FROM Win32_Printer") 'Or "SELECT * FROM CIM_Printer"
'Create a filter to rule out some "non-printers"
_Query.Condition = "NOT DeviceID LIKE '%fax%' AND NOT DeviceID LIKE '%xps%' AND NOT DeviceID LIKE '%PDF%'"
Dim _Options As New EnumerationOptions()
_Options.Timeout = EnumerationOptions.InfiniteTimeout
'Forward only query => no caching
_Options.Rewindable = False
'Pseudo-async result
_Options.ReturnImmediately = True
Dim _searcher As New ManagementObjectSearcher(_Scope, _Query, _Options)
For Each _objPrinter As ManagementObject In _searcher.Get()
Dim _Printer As New Printer()
_Printer.PrinterName = _objPrinter.Properties("Name").Value.ToString()
_Printer.PrinterPort = _objPrinter.Properties("PortName").Value.ToString()
_Printer.PrinterDriver = _objPrinter.Properties("DriverName").Value.ToString()
_Printer.PrintProcessor = _objPrinter.Properties("PrintProcessor").Value.ToString()
_Printer.DeviceID = _objPrinter.Properties("DeviceID").Value.ToString()
_Printer.Status = CType(_objPrinter.Properties("PrinterStatus").Value, PrinterStatus)
_Printer.IsLocalPrinter = If(_objPrinter.Properties("Local").Value.ToString() = "True", True, False)
_Printer.IsNetworkPrinter = If(_objPrinter.Properties("Network").Value.ToString() = "True", True, False)
_Printer.IsDefaultPrinter = If(_objPrinter.Properties("Default").Value.ToString() = "True", True, False)
Dim _PrinterProps As New List(Of PrinterProperties)()
For Each _oBJData As PropertyData In _objPrinter.Properties
_PrinterProps.Add(New PrinterProperties() With {
.PropertyName = _oBJData.Name,
.PropertyValue = If(_oBJData.Value IsNot Nothing, _oBJData.Value.ToString(), ""),
.PropertyValueType = _oBJData.Type.ToString(),
.PropertyIsArray = _oBJData.IsArray
})
Next
_Printer.PrinterProperties = _PrinterProps
_Printers.Add(_Printer)
Next
Return _Printers
End Function
Relative Objects:
Public Enum PrinterStatus As Integer
Other = 1
Unknown = 2
Ready = 3
Printing = 4
Warmup = 5
StoppedPrinting = 6
Offline = 7
End Enum
Public Class Printer
Public Property PrinterName() As String
Public Property PrinterPort() As String
Public Property PrinterDriver() As String
Public Property PrintProcessor() As String
Public Property DeviceID() As String
Public Property Status() As PrinterStatus
Public Property IsDefaultPrinter() As Boolean
Public Property IsLocalPrinter() As Boolean
Public Property IsNetworkPrinter() As Boolean
Public Property PrinterProperties() As List(Of PrinterProperties)
End Class
Public Class PrinterProperties
Public Property PropertyName() As String
Public Property PropertyValue() As String
Public Property PropertyValueType() As String
Public Property PropertyIsArray() As Boolean
End Class