关于您当前的情况,您可以尝试设置两个策略:
- 仅使用通用打印
- 不要自动创建客户端打印机
然后强制更新组策略(客户端)。
也许您希望客户端和服务器打印机相互镜像,但只是为了测试。
(但是请注意,在不同情况下,我在 WMI 枚举中看到的时间比 15 秒差得多。另请注意,我m 不是 Citrix Sessions/UPS 方面的专家。)
WMI SQL (WQL) 是 ANSI SQL 标准的子集。请参阅:
Querying with WQL -
WQL (SQL for WMI) Keywords
当然,它会返回一组与查询中定义的约束相匹配的记录(对象)。
它是一个高效的系统吗?在这件事上你可能会听到非常不同的意见。
第一个查询速度较慢,因为此时会创建新对象。
如果没有其他指示,WMI 会缓存这些对象以供后续查询。
请参阅
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%'"
以下测试是在一台有 7 台打印机的机器上进行的,其中 3 台是“非打印机”:Fax、XPS Driver 和 PDF Driver。其他 4 台是“真正的”打印机:2 台是本地打印机,2 台是网络打印机。
QUERY MIN MAX
One Printer: 96ms - 181ms
All Printers: (7) 107ms - 190ms
Filtered: (4) 108ms - 229ms
使用 StopWatch 测量 50 次迭代
Dim _SW As Stopwatch = Stopwatch.StartNew()
Dim _Printers As List(Of Printer) = GetSystemPrinters()
Console.WriteLine(_SW.ElapsedMilliseconds.ToString())
这是使用的代码和对象:
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
相对对象:
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