升级到Windows 10后WMI无法正常工作

我一直在Windows 8上使用Visual Studio中的控制台应用程序的代码来返回连接的串行设备的描述和设备ID。 我在我正在创建的应用程序中使用这个的修改版本来自动检测Arduino的COM端口。 自从我使用Windows 10进行全新安装后,它不再返回任何内容。我有一个USB转串口AVR程序员,但仍然显示使用此代码。 我检查了注册表,Arduino列在SERIALCOMM中,Arduino在Device Manager中的’Ports(COM&LPT)’下显示为’USB Serial Port(COM6)’,我可以使用Arduino软件对Arduino进行编程。 我不知道它为什么不再工作了。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Management; using System.IO.Ports; using System.Diagnostics; namespace ConsoleApplication1 { class Program { static void Main() { ManagementScope connectionScope = new ManagementScope(); SelectQuery serialQuery = new SelectQuery("SELECT * FROM Win32_SerialPort"); ManagementObjectSearcher searcher = new ManagementObjectSearcher(connectionScope, serialQuery); try { foreach (ManagementObject item in searcher.Get()) { string desc = item["Description"].ToString(); string deviceId = item["DeviceID"].ToString(); Console.WriteLine(desc); Console.WriteLine(deviceId); } } catch (ManagementException e) { Console.WriteLine(e.Message); } Console.ReadKey(); } } } 

在尝试找到解决方案时,我发现以下实现可以使用MSSerial_PortName查找端口名称,并且我收到了拒绝访问错误。

 using System; using System.Management; namespace ConsoleApplication1 { class Program { static void Main() { try { ManagementObjectSearcher MOSearcher = new ManagementObjectSearcher("root\\WMI", "SELECT * FROM MSSerial_PortName"); foreach (ManagementObject MOject in MOSearcher.Get()) { Console.WriteLine(MOject["PortName"]); } } catch (ManagementException me) { Console.WriteLine("An error occurred while querying for WMI data: " + me.Message); } Console.ReadKey(); } } } 

好吧,我想我现在看到了这个问题(我将添加一个新答案,但如果有人发现信息有用,则不会替换旧答案)。

Win32_SerialPort仅检测硬件串行端口(例如RS232)。 Win32_PnPEntity标识即插即用设备,包括硬件和虚拟串行端口(例如,由FTDI驱动程序创建的COM端口)。

要使用Win32_PnPEntity来识别驱动程序需要一些额外的工作。 以下代码标识系统上的所有COM端口,并生成所述端口的列表。 从此列表中,您可以标识相应的COM端口号以创建SerialPort对象。

 // Class to contain the port info. public class PortInfo { public string Name; public string Description; } // Method to prepare the WMI query connection options. public static ConnectionOptions PrepareOptions ( ) { ConnectionOptions options = new ConnectionOptions ( ); options . Impersonation = ImpersonationLevel . Impersonate; options . Authentication = AuthenticationLevel . Default; options . EnablePrivileges = true; return options; } // Method to prepare WMI query management scope. public static ManagementScope PrepareScope ( string machineName , ConnectionOptions options , string path ) { ManagementScope scope = new ManagementScope ( ); scope . Path = new ManagementPath ( @"\\" + machineName + path ); scope . Options = options; scope . Connect ( ); return scope; } // Method to retrieve the list of all COM ports. public static List FindComPorts ( ) { List portList = new List ( ); ConnectionOptions options = PrepareOptions ( ); ManagementScope scope = PrepareScope ( Environment . MachineName , options , @"\root\CIMV2" ); // Prepare the query and searcher objects. ObjectQuery objectQuery = new ObjectQuery ( "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0" ); ManagementObjectSearcher portSearcher = new ManagementObjectSearcher ( scope , objectQuery ); using ( portSearcher ) { string caption = null; // Invoke the searcher and search through each management object for a COM port. foreach ( ManagementObject currentObject in portSearcher . Get ( ) ) { if ( currentObject != null ) { object currentObjectCaption = currentObject [ "Caption" ]; if ( currentObjectCaption != null ) { caption = currentObjectCaption . ToString ( ); if ( caption . Contains ( "(COM" ) ) { PortInfo portInfo = new PortInfo ( ); portInfo . Name = caption . Substring ( caption . LastIndexOf ( "(COM" ) ) . Replace ( "(" , string . Empty ) . Replace ( ")" , string . Empty ); portInfo . Description = caption; portList . Add ( portInfo ); } } } } } return portList; } 

比Juderb小一点的解决方案

  public static List FindComPorts() { using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0")) { return searcher.Get().OfType() .Select(port => Regex.Match(port["Caption"].ToString(), @"\((COM\d*)\)")) .Where(match => match.Groups.Count >= 2) .Select(match => match.Groups[1].Value).ToList(); } } 

在win7 + win10上测试过。 顺便说一句,你可以根据需要为正则表达式添加额外的搜索条件(或者只是添加一个新的Where子句)

Windows 10用户配置文件可能包含完全管理员权限,而Windows 10用户配置文件是标准用户。 由于您的Windows 10用户配置文件是标准用户,因此您必须调整一些访问权限。

  1. 运行Computer Management实用程序。

  2. 转到Computer Management > Services and Applications > WMI Control

  3. 转到“ Actions > WMI Control > More Actions > Properties以打开“ WMI Control Properties窗口。

  4. Security选项卡下,选择Root ,然后按Security

  5. Security for Root对话框中,选择您的用户名或您所属的组。 选择“ Allow for Permissions > Execute Methods 。 单击“ OK关闭对话框。

  6. CIMV2重复上一步。

  7. 尝试使用这些新权限再次运行。

电脑管理工具 Root的WMI控件属性 CIMV2的WMI控件属性 Root的安全选项