这一小段代码对此表现非常好(返回COM端口字符串,如果检测到Arduino则返回"COM12"):
private string AutodetectArduinoPort() { 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(); if (desc.Contains("Arduino")) { return deviceId; } } } catch (ManagementException e) { /* Do Nothing */ } return null; }
您可以使用SerialPort.GetPortNames()返回字符串COM端口名称的数组.
我不认为你可以自动检测端口,你必须ping设备,以查看设备是否已连接.
进一步采用WMI管理路径,我想出了一个包装类,它挂接到Win32_SerialPorts事件,并动态填充了Arduino和Digi International(X-Bee)设备的SerialPort列表,以及PortNames和BaudRates.
现在,我已经使用Win32_SerialPorts条目中的设备描述字段作为字典的键,但这很容易改变.
它已经通过Arduino UNO进行了有限的测试,看起来很稳定.
// ------------------------------------------------------------------------- //// Copyright (c) ApacheTech Consultancy. All rights reserved. // //// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see http://www.gnu.org/licenses // // ------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO.Ports; using System.Linq; using System.Management; using System.Runtime.CompilerServices; // Automatically imported by Jetbeans Resharper using ArduinoLibrary.Annotations; namespace ArduinoLibrary { /// /// Provides automated detection and initiation of Arduino devices. This class cannot be inherited. /// public sealed class ArduinoDeviceManager : IDisposable, INotifyPropertyChanged { ////// A System Watcher to hook events from the WMI tree. /// private readonly ManagementEventWatcher _deviceWatcher = new ManagementEventWatcher(new WqlEventQuery( "SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2 OR EventType = 3")); ////// A list of all dynamically found SerialPorts. /// private Dictionary_serialPorts = new Dictionary (); /// /// Initialises a new instance of the public ArduinoDeviceManager() { // Attach an event listener to the device watcher. _deviceWatcher.EventArrived += _deviceWatcher_EventArrived; // Start monitoring the WMI tree for changes in SerialPort devices. _deviceWatcher.Start(); // Initially populate the devices list. DiscoverArduinoDevices(); } ///class. /// /// Gets a list of all dynamically found SerialPorts. /// ///A list of all dynamically found SerialPorts. public DictionarySerialPorts { get { return _serialPorts; } private set { _serialPorts = value; OnPropertyChanged(); } } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { // Stop the WMI monitors when this instance is disposed. _deviceWatcher.Stop(); } ////// Occurs when a property value changes. /// public event PropertyChangedEventHandler PropertyChanged; ////// Handles the EventArrived event of the _deviceWatcher control. /// /// The source of the event. /// Theinstance containing the event data. private void _deviceWatcher_EventArrived(object sender, EventArrivedEventArgs e) { DiscoverArduinoDevices(); } /// /// Dynamically populates the SerialPorts property with relevant devices discovered from the WMI Win32_SerialPorts class. /// private void DiscoverArduinoDevices() { // Create a temporary dictionary to superimpose onto the SerialPorts property. var dict = new Dictionary(); try { // Scan through each SerialPort registered in the WMI. foreach (ManagementObject device in new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_SerialPort").Get()) { // Ignore all devices that do not have a relevant VendorID. if (!device["PNPDeviceID"].ToString().Contains("VID_2341") && // Arduino !device["PNPDeviceID"].ToString().Contains("VID_04d0")) return; // Digi International (X-Bee) // Create a SerialPort to add to the collection. var port = new SerialPort(); // Gather related configuration details for the Arduino Device. var config = device.GetRelated("Win32_SerialPortConfiguration") .Cast ().ToList().FirstOrDefault(); // Set the SerialPort's PortName property. port.PortName = device["DeviceID"].ToString(); // Set the SerialPort's BaudRate property. Use the devices maximum BaudRate as a fallback. port.BaudRate = (config != null) ? int.Parse(config["BaudRate"].ToString()) : int.Parse(device["MaxBaudRate"].ToString()); // Add the SerialPort to the dictionary. Key = Arduino device description. dict.Add(device["Description"].ToString(), port); } // Return the dictionary. SerialPorts = dict; } catch (ManagementException mex) { // Send a message to debug. Debug.WriteLine(@"An error occurred while querying for WMI data: " + mex.Message); } } /// /// Called when a property is set. /// /// Name of the property. [NotifyPropertyChangedInvocator] private void OnPropertyChanged([CallerMemberName] string propertyName = null) { var handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } } }