2015-12-02 3 views
4

Я использовал приведенный ниже код для консольного приложения в Visual Studio в Windows 8, чтобы вернуть описание и идентификатор устройства подключенных последовательных устройств. Я использовал модифицированную версию этого в приложении, которое я создаю, чтобы автоматически обнаруживать COM-порт Arduino. Он больше не возвращает ничего, так как я сделал новую установку с Windows 10. У меня есть USB-последовательный AVR-программник, который все еще появляется с использованием этого кода. Я проверил реестр, и Arduino указан в SERIALCOMM, Arduino отображается как «USB-последовательный порт (COM6)» под «Ports» (COM & LPT) »в диспетчере устройств, и я могу запрограммировать Arduino с помощью программного обеспечения Arduino. Я понятия не имею, почему он больше не работает.WMI не работает после обновления до Windows 10

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

Звучит как проблема аутентификации. Передайте экземпляр ConnectionOptions в свой конструктор ManagementScope, определяя свойства аутентификации и олицетворения. – Juderb

+0

Спасибо @Juderb Я просто использую это локально на своей собственной машине, и я попробовал ваше предложение, и я установил ImpersonationLevel для Impersonate (который является единственным уровнем, на котором он будет работать), и я попробовал все различные параметры для AuthenticationLevel и кода все равно будет только найти мой USB для Serial AVR Programmer, но не мой Arduinos. Добавление AuthenticationLevel и ImpersonationLevel ко второму блоку кода, который я опубликовал, который использует MSSerial_PortName, не имеет никакого значения, я все же получил Access Denied (со всеми различными комбинациями уровней олицетворения и аутентификации). – thoward

+0

Пользователь по умолчанию не может получить доступ к системным устройствам! Нужно запускать как администратор для разделяемой библиотеки или устройств ... – dsgdfg

ответ

4

Хорошо, я думаю, я вижу этот вопрос сейчас (я добавлю новый ответ, но не заменит старый в случае, если кто-то находит эту информацию полезной) ,

Win32_SerialPort обнаруживает только последовательные порты устройства (например, RS232). Win32_PnPEntity определяет устройства plug-and-play, включая аппаратные и виртуальные последовательные порты (например, COM-порт, созданный драйвером FTDI).

Для использования драйвера 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<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; 
} 
+0

Удивительно, что работает, спасибо! – thoward

+0

Отлично, рад это слышать! Удивительно, как может быть запутанное упражнение, работающее с WMI. – Juderb

+1

Я взял на себя смелость исправлять несколько опечаток в коде: поля 'options' были неправильными. –

1

Ваш профиль пользователя Windows 8, вероятно, содержит полные права администратора, в то время как ваш профиль пользователя 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. Попробуйте снова использовать эти новые разрешения.

Computer Management Utility WMI Control Properties for Root WMI Control Properties for CIMV2 Security Options for Root

+0

Я попробовал ваше предложение, и оно все еще не работает. Тот факт, что при использовании Win32_SerialPort (в отличие от MSSerial_PortName) он может найти моего USB-программатора AVR, но не мой Arduino заставляет меня думать, что это не проблема, связанная с разрешением. Интересно, что, как я уже упоминал, он работает для USB-AVR-программиста, который установлен с помощью драйвера от производителя программиста (Pololu) и не работает для моего Arduino и USB-последовательного адаптера, который у меня есть, оба из которых установлены как " USB Serial Port "с производителем, указанным как FTDI (они делают USB для последовательного интерфейса IC на этих устройствах). – thoward

+0

@thoward, дайте мой второй ответ попробовать. Это подход, который я использую для нескольких компонентов в полностью автоматизированной системе микроскопии и медицинского устройства класса III (т. Е. Его надежной при правильной реализации). – Juderb

2

немного меньше, чем раствор 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(); 
     } 
    } 

Испытано это на win7 + win10. Btw, вы можете добавить дополнительные критерии поиска в регулярное выражение, если хотите (или просто добавить новое предложение Where)

+1

Гораздо чище, чем мое оригинальное решение. – Juderb

Смежные вопросы