WMI not working after upgrading to Windows 10

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-01 05:32:27

问题


I had been using the code below for a console application in Visual Studio on Windows 8 to return the description and device ID of connected serial devices. I was using a modified version of this in an application I'm creating to automatically detect the COM port of an Arduino. It no longer returns anything since I've done a fresh install with Windows 10. I have a USB to serial AVR programmer that still shows up using this code however. I checked the registry and the Arduino is listed in SERIALCOMM, the Arduino is showing as 'USB Serial Port (COM6)' under 'Ports (COM & LPT)' in Device Manager and I can program the Arduino using the Arduino software. I have no idea why it isn't working any more.

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();
        }
    }
}

It might also be relevant that while trying to find a solution I found the following implementation to find port names using MSSerial_PortName and I got an Access Denied error.

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();
        }
    }
}

回答1:


Ok, I think I see the issue now (I will add a new answer, but won't replace the old in case someone finds the information useful).

Win32_SerialPort only detects hardware serial ports (e.g. RS232). Win32_PnPEntity identifies plug-and-play devices including hardware and virtual serial ports (e.g. COM port created by the FTDI driver).

To use Win32_PnPEntity to identify a driver requires a little extra work. The following code identifies all COM ports on the system and produces a list of said ports. From this list, you may identify the appropriate COM port number to create your SerialPort object.

// 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<PortInfo> FindComPorts ( )
{
  List<PortInfo> portList = new List<PortInfo> ( );
  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;
}



回答2:


A bit smaller solution than Juderb

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

Tested this on win7 + win10. Btw, you can add extra search criteria to the regex if you want (or just add a new Where clause)




回答3:


Your Windows 8 user profile probably included full administrator privileges while your Windows 10 user profile is a standard user. Because your Windows 10 user profile is a standard user, you must adjust some access permissions.

  1. Run the Computer Management utility.

  2. Go to Computer Management > Services and Applications > WMI Control.

  3. Go to Actions > WMI Control > More Actions > Properties to open the WMI Control Properties window.

  4. Under the Security tab, select Root, then press Security.

  5. In the Security for Root dialog, select your username or the group you belong to. Select Allow for Permissions > Execute Methods. Click OK to close the dialog.

  6. Repeat the previous step for CIMV2.

  7. Try running again with these new permissions.



来源:https://stackoverflow.com/questions/34034688/wmi-not-working-after-upgrading-to-windows-10

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!