首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# 代碼解析:透過 WMI 查詢序列埠並提取特定廠商設備資訊

     編輯:程式設計綜合問答

代碼功能概述

該方法 GetSerialPort() 透過 WMI (Win32_SerialPort) 列舉系統序列埠,尋找 Name 屬性前 6 字元為 "STMicr" (STMicroelectronics) 的設備,並嘗試提取第 38-42 字元作為結果。

原始代碼存在的 Bug

  1. Substring 索引越界:strs.Substring(37, 5) 要求字串長度 ≥ 42,實際 Name 可能更短,會拋出 ArgumentOutOfRangeException。
  2. 迴圈覆蓋結果:每次迴圈將 strs 覆寫,最終返回最後一個符合條件的設備片段,而非第一個或所有匹配項。
  3. 邏輯倒置:若首個設備不匹配,strs 被設為 "No Found",後續匹配設備會被覆蓋為 "No Found"(因 else 分支)。
  4. 硬編碼魔術數字:37、5、6 無語義常數,維護困難。

修正後的健壯實現

public static string GetStmSerialPortSuffix() {
    const string targetPrefix = "STMicr";
    const int prefixLen = 6;
    const int extractStart = 37;
    const int extractLen = 5;

    using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_SerialPort")) {
        foreach (ManagementObject port in searcher.Get()) {
            string name = port["Name"]?.ToString() ?? "";
            if (name.Length >= prefixLen && name.Substring(0, prefixLen).Equals(targetPrefix, StringComparison.OrdinalIgnoreCase)) {
                if (name.Length >= extractStart + extractLen) {
                    return name.Substring(extractStart, extractLen);
                }
                // 長度不足時的 fallback:返回可用部分或空
                return name.Length > extractStart ? name.Substring(extractStart) : "";
            }
        }
    }
    return "Not Found"; // 統一返回語義
}

關鍵改進點

  • using 確保 ManagementObjectSearcher 釋放非托管資源。
  • 常數化魔術數字,增強可讀性。
  • 空值保護 ?.ToString() ?? ""。
  • 長度檢查防越界。
  • 找到即返回,避免無謂迴圈與覆蓋邏輯。
  • 大小寫不敏感比較,兼容 WMI 返回差異。

擴展建議

  • 若需支援多設備,返回 List<string> 收集所有匹配項。
  • 若需更豐富資訊(VID/PID、COM 埠號),查詢 Win32_SerialPort 的 DeviceID、PNPDeviceID 等屬性。
  • 考慮緩存 WMI 查詢結果,避免頻繁呼叫開銷。

WMI 查詢雖強大,但返回數據格式不穩定,防禦性編程(長度檢查、空值處理、異常捕獲)是生產級代碼的必修課。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved