SELECT * FROM Win32_Printer

时间:2018-01-16 19:33:51

标签: vb.net printing wmi citrix .net-4.6.1

我正在更新一些例程,这些例程有助于识别和存储用户在通过Citrix访问我们的应用程序时可用的打印机。创建打印机后,它们会标记为;

在Citrix;

会话209中的PrinterName(来自MyTerminalID)

在RDP中;

PrinterName(重定向209)

在本地运行我们只需获取PrinterName

这一切都很好但我们已经从使用" system.drawing"识别有些危险的打印机的方法,并将citrix节点上的每台打印机识别为使用System.Management查询SELECT * FROM Win32_Printer

我已使用条件DeviceID Like '%(from MyTerminalID)%' AND DeviceID LIKE '%in session 123'对其进行了修改,但第一次执行查询时,在返回结果之前可能需要几秒钟(15+)。我得到的结果很快。

现在的问题是,我怎样才能让它变得更快?

我唯一感兴趣的是获取与myTerminalID和我的会话或我的会话相关的打印机子集(如果是RDP,但是citrix版本是重要的位)。

查询是否像正确的SQL查询一样运行,因此将使用条件来减少运行时间,或者更多的是伪查询,它将撤回整个数据集,然后应用过滤

有没有办法减少它需要去的数据量(例如,如果我使用SELECT DeviceID而不是SELECT *)。

重新运行查询要快得多<1秒。在某些方面,如果按照目前用于设置的打印机列表需要15秒以上时间并不重要,但还有另一个例程可检查以前选择的打印机是否仍然可用对同一终端上的用户(即使其他用户是设置它们的用户)。我还想尝试并可能过滤掉非打印机&#34;像传真机一样,为此,我需要查看一些属性的细节。

1 个答案:

答案 0 :(得分:0)

关于您当前的情况,您可以尝试设置两项政策:
  - 仅使用通用打印   - 不要自动创建客户端打印机

然后强制更新组策略(客户端)。

也许您希望客户端和服务器打印机相互镜像,但仅用于测试。
(但请注意,在不同情况下,我看到WMI枚举中的时间比15秒差很多。请注意我在Citrix会话/ 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台是“非打印机”:传真,XPS驱动程序和PDF驱动程序。其他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