首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 透過 WMI 取得網卡 MAC 位址與硬碟磁碟區序號

     編輯:關於C語言

前言

在軟體授權、裝置指紋、資產管理等場景,常需取得機器唯一識別碼。本文示範使用 System.Management 命名空間(WMI)查詢 Win32_NetworkAdapterConfiguration 取得啟用中網卡的 MAC 位址,以及 Win32_LogicalDisk 取得系統磁碟(通常為 C:)的磁碟區序號。

完整程式碼

using System;
using System.Management;
using System.Linq;

namespace HardwareInfo
{
    public static class DeviceIdentifier
    {
        /// 
        /// 取得第一張啟用 IP 的網卡 MAC 位址(不含冒號)
        /// 
        public static string GetMacAddress()
        {
            try
            {
                using (var mc = new ManagementClass("Win32_NetworkAdapterConfiguration"))
                using (var moc = mc.GetInstances())
                {
                    foreach (ManagementObject mo in moc)
                    {
                        if ((bool)mo["IPEnabled"] == true)
                        {
                            string mac = mo["MacAddress"]?.ToString();
                            if (!string.IsNullOrWhiteSpace(mac))
                                return mac.Replace(":", "").Replace("-", "").ToUpperInvariant();
                        }
                    }
                }
            }
            catch (ManagementException ex)
            {
                // 記錄日誌:WMI 查詢失敗
            }
            return string.Empty;
        }

        /// 
        /// 取得指定磁碟機(預設 C:)的磁碟區序號
        /// 
        public static string GetVolumeSerialNumber(string driveLetter = "C")
        {
            try
            {
                string query = $"SELECT VolumeSerialNumber FROM Win32_LogicalDisk WHERE DeviceID = '{driveLetter}:'";
                using (var searcher = new ManagementObjectSearcher(query))
                using (var results = searcher.Get())
                {
                    foreach (ManagementObject disk in results)
                    {
                        string serial = disk["VolumeSerialNumber"]?.ToString();
                        if (!string.IsNullOrWhiteSpace(serial))
                            return serial.ToUpperInvariant();
                    }
                }
            }
            catch (ManagementException ex)
            {
                // 記錄日誌
            }
            return string.Empty;
        }
    }
}

關鍵技術細節

1. WMI 查詢優化

  • 使用 ManagementObjectSearcher + WQL 條件篩選(WHERE DeviceID = 'C:'),避免枚舉所有磁碟再過濾。
  • 所有 ManagementObject、ManagementClass、ManagementObjectCollection 皆實作 IDisposable,務必包在 using 區塊釋放非受控資源。

2. MAC 位址處理

  • 原始格式含分隔符(00:1A:2B:3C:4D:5E 或 00-1A-2B-3C-4D-5E),統一移除並轉大寫便於比對。
  • 僅抓取 IPEnabled == true 的實體網卡,避開虛擬介面(Hyper-V、VPN、Loopback)。

3. 磁碟區序號 vs 硬碟序號

項目磁碟區序號 (VolumeSerialNumber)硬碟實體序號 (SerialNumber)
來源Win32_LogicalDiskWin32_DiskDrive
層級邏輯分割區(格式化時產生)實體裝置(出廠燒錄)
重裝系統後改變不變
適用場景簡易授權綁定、快速指紋嚴格裝置綁定、防盜版

注意:本範例取得的是磁碟區序號,重新格式化或重裝系統會改變。若需更穩定的硬體 ID,請改查 Win32_DiskDrive.SerialNumber 或 Win32_BaseBoard.SerialNumber(主機板)。

常見問題與解決方案

Q: 執行時拋出 ManagementException: Invalid namespace?
A: 目標機器可能未安裝 WMI 提供者或服務未啟動。請確認 winmgmt 服務正在執行,或嘗試 mofcomp.exe 重新註冊。
Q: 取得的 MAC 為空或 "00:00:00:00:00:00"?
A: 虛擬機、Docker 容器、某些 VPN 介面可能回傳全零。建議加入過濾:排除 Description 含 "Virtual"、"VPN"、"Hyper-V" 的介面。
Q: 權限不足無法查詢 WMI?
A: 需以管理員權限執行,或將應用程式加入「效能監視使用者」群組。ASP.NET Core 應用請設定 runAsAdministrator 或使用服務帳號。
Q: .NET Core / .NET 5+ 專案找不到 System.Management?
A: 需安裝 NuGet 套件 System.Management(Windows 專用),並確認專案目標框架包含 net6.0-windows 等 Windows 專用 TFM。

進階:組合成裝置指紋

public static string GenerateDeviceFingerprint()
{
    string mac = GetMacAddress();
    string vol = GetVolumeSerialNumber("C");
    string cpuId = GetCpuId(); // 需另行實作 Win32_Processor.ProcessorId
    string raw = $"{mac}|{vol}|{cpuId}";
    using (var sha256 = System.Security.Cryptography.SHA256.Create())
    {
        byte[] hash = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(raw));
        return Convert.ToHexString(hash).Substring(0, 32); // 取前 32 字元
    }
}

總結

透過 WMI 取得 MAC 位址與磁碟區序號是 Windows 平台常見的硬體識別手法。掌握 WQL 查詢、資源釋放、權限需求與虛擬環境干擾等細節,才能在實務專案中穩定運作。若需更高安全性,建議結合 TPM、安全啟動或雲端驗證機制。

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