部分解
方法一
最簡單的方法,就是直接利用 SerialPort 這個 Class 來取得。
// A string array consists of port names.
string[] ports2 = SerialPort.GetPortNames();
所以假如你電腦上連接 Arduino(COM7),我們就可以把收到的 Port 放在一個 ComboBox 下拉式選單裡。
摁?要是不看裝置管理員還真不知道 Arduino 被放在 COM7,這種方式雖然可行但太不直觀,於是我們想要取得更詳細一點的資訊,這時就可以利用方法二。
方法二
這個方法是利用 ManagementObjectSearcher 這個 Class 去向電腦撈取所有連接裝置的詳細資料。DeviceID 就是之後要連 Serial Port 時可以識別的字串,而 Caption 就是我們想要的連接埠註解,程式如下。
var searcher = new ManagementObjectSearcher("SELECT DeviceID,Caption FROM WIN32_SerialPort");
foreach (ManagementObject port in searcher.Get())
{
// ex: COM7
string name = port.GetPropertyValue("DeviceID").ToString();
// ex: Arduino Uno (COM7)
string description = port.GetPropertyValue("Caption").ToString();
// do what ever you want...
}
讓我們來看看結果,成功…嗎?似乎少了什麼,第一張圖中的 COM6 這個 Port 不見了!
事實上,連接在 COM6 上的是一個 USB 轉 TTL/RS232 序列傳輸介面,由於他只是一個類似轉接頭的東西,並不是一個裝置,所以用第二個方法會把這個 Port 給漏掉,不過如果沒有此需求的話,其實這樣就可以了。
用這個方法記得要在專案中加入參考 System.Management,才可以編譯成功。位置在主選單的專案→加入參考→組件→勾選 System.Management→確定。
完整解
為了找到 USB 轉 TTL/RS232 序列傳輸介面,只好沿用第一個方法補上。另外,為了存放這些 Port 的名稱跟描述,自己寫了一個 ComProt 的結構去做存取。
// custom struct with our desired values
struct ComPort
{
public string name;
public string description;
public ComPort(string name, string description)
{
this.name = name;
this.description = description;
}
}
// Method 2 function
private List<ComPort> GetSerialPort2()
{
List<ComPort> ports = new List<ComPort>();
var searcher = new ManagementObjectSearcher("SELECT DeviceID,Caption FROM WIN32_SerialPort");
foreach (ManagementObject port in searcher.Get())
{
// show the service
ComPort c = new ComPort();
c.name = port.GetPropertyValue("DeviceID").ToString();
c.description = port.GetPropertyValue("Caption").ToString();
ports.Add(c);
}
return ports;
}
private List<ComPort> GetAllPorts()
{
// Method 2
List<ComPort> ports = GetSerialPort2();
foreach (ComPort port in ports)
{
ports.Add(port);
}
// Method 1
string[] ports2 = SerialPort.GetPortNames();
foreach (string port in ports2)
{
// Only need to check the Port Name
if (!ports.Exists(x => x.name == port))
{
ports.Add(new ComPort(port, port));
}
}
return ports;
}
在 GetAllPorts 涵式中,做了一些檢查以免有 Port 重複出現,這樣就可以獲取到所有連接到電腦上的裝置了,把得到的 Port 們放到一個 ComboBox 下拉式選單裡。
搞定!
題外話
關於方法二,其實是利用了 Windows 內建的 WMI 物件,想要快速查看某個類別裡有什麼東西時,也可以直接打開 Powershell 使用 gwmi 指令,例如方法二中我們想看的 Win32_DriveDisk
:
PS> gwmi Win32_DriveDisk