如何使用LINQ查询ManagementObjectCollection,然后通过PropertyData循环返回ManagementObject?

问题描述 投票:1回答:1

[C#.NET Windows窗体WMI]

我是C#的新手,但我有使用VBScript的经验,我正在尝试将我编写的脚本转换为C#。我不是只使用转换器,而是重写代码并尝试对其进行优化,以帮助我学习。

一点背景

在我原来的VBScript中,我使用以下代码连接到远程服务器:

Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServices = objSWbemLocator.ConnectServer(strComputer, "root\cimv2", strUserName, strPassword)
objSWbemServices.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate

然后我遍历我正在寻找的打印机列表并调用具有以下代码的函数:

Set colPorts = objConnection.ExecQuery("SELECT * FROM Win32_Printer WHERE Name = '" & strPrinter & "'")  

If colPorts.Count = 0 Then
    Set objPort = objConnection.Get("Win32_TCPIPPrinterPort").SpawnInstance_

在生成实例之后,我将我想要的属性添加到具有任意字符串值的Dictionary对象,其中我正在搜索的打印机作为键,属性作为值。因此,当我与服务器断开连接时,我有一个字典对象,其中包含我需要从该服务器处理的所有打印机(我也使用端口做同样的事情)。

使用C#,它看起来不需要使用字典,因为我可以使用ManagementObjectSearcher返回ManagementObjectCollection。然后,如果我理解正确,我应该能够从单个ManagementObject获取我想要的特定打印机所需的属性,或者向下钻取到PropertyData。和我一起到目前为止?

问题/机会

因为我正在返回整个集合,我认为使用LINQ找到我需要使用的特定打印机而不是循环遍历整个集合会更有效率。然后,一旦我从LINQ获得ManagementObject,我可以将PropertyData分配给变量供以后使用(假设可能)或循环通过PropertyData来查看内容(主要用于调试)。

我用以下代码尝试了后者而没有任何运气:

var printer = from ManagementObject x in mocPrinters
                      where x.Properties["Name"].Value.ToString() == "MyHP"
                      select x;

foreach (PropertyData p in printer)
{
    MessageBox.Show(string.format("{0}: {1}", p.Name, p.Value);
}

上面的代码没有用,因为我假设我的打印机不是PropertyData类型。

其他有用的信息

我认为在返回整个集合后查询LINQ会比使用WMI / WQL SELECT * FROM Win32_Printer WHERE Name = 'MyHP'查询更快,但是如果有人测试了这一点并且知道性能差异可以忽略不计,那我就满足于使用WMI / WQL(我是作为程序员来测试这些东西还不够精明)。

如果有人有任何指示,我将不胜感激。谢谢...

c# .net winforms linq wmi
1个回答
2
投票

目前你有一个ManagementObjects的集合,你需要一个PropertyData的集合。

我认为你的意思是这样的:

var printers = from ManagementObject x in mocPrinters
                      where x.Properties["Name"].Value.ToString() == "MyHP"
                      select x;

foreach (PropertyData p in printers.First().Properties)
{
    MessageBox.Show(string.format("{0}: {1}", p.Name, p.Value);
}

将WMI用于其他任务的经验是,在查询中包含过滤时执行速度更快。 LINQ不是关于计算效率,而是关于表达性。

访问属性的最快方法是直接构建WMI路径。在打印机的情况下,似乎路径中使用的DeviceID是名称。所以你可以使用以下方法获取对象:

var printer = new ManagementObject("Win32Printer.DeviceID=\"MyHP\"");

当然,这适用于本地系统上的打印机,但是为远程机器构建路径也相对容易。

© www.soinside.com 2019 - 2024. All rights reserved.