您实际上拥有 MotherboardID、CPUID、磁盘序列号和 MAC 地址,根据经验,它们都不是 100%。
我们的数据显示
- 磁盘序列号缺失 0.1 %
- MAC 丢失 1.3 %
- 主板 ID 缺失 30 %
- CPUID 缺失 99 %
0.04% 的机器测试它们没有产生任何信息,我们甚至无法读取计算机名称。也许这些是虚拟 PC、HyperV 或 VMWare 实例之上的某种类型?
磁盘序列是最可靠的,但易于更改,mac 可以更改,如果添加设备驱动程序(hyperv、wireshark 等),根据应用的过滤可以更改。
主板和 CPUID 有时会返回占位符“NONE”等值。
您还应该注意,这些函数的调用速度可能非常慢(即使在快速的 PC 上也可能需要几秒钟),因此可能值得尽早在后台线程上启动它们,最好不要不想被他们挡住。
主板 ID
private static void FetchMotherboardIdInternal()
{
try
{
ManagementScope scope = new ManagementScope("\\\\" + Environment.MachineName + "\\root\\cimv2");
scope.Connect();
using (ManagementObject wmiClass = new ManagementObject(scope, new ManagementPath("Win32_BaseBoard.Tag=\"Base Board\""), new ObjectGetOptions()))
{
object motherboardIDObj = wmiClass["SerialNumber"];
if (motherboardIDObj != null)
{
string motherboardID = motherboardIDObj.ToString().Trim();
Trace.WriteLine("MotherboardID = " + motherboardID);
if (IsValidMotherBoardID(motherboardID))
{
_motherboardID = motherboardID;
}
}
}
}
catch (System.Threading.ThreadAbortException)
{
throw;
}
catch (Exception ex)
{
Trace.TraceWarning("Failed to read MotherbaordID\r\n" + ex.Message);
}
}
public static bool IsValidMotherBoardID(string value)
{
if (value == null)
return false;
string motherboardID = value.Trim();
return !( motherboardID.Replace(".", "").Replace(" ", "").Replace("\t", "").Trim().Length < 5 ||
motherboardID.ToUpper().Contains("BASE") ||
motherboardID.Contains("2345") ||
motherboardID.ToUpper().StartsWith("TO BE") ||
motherboardID.ToUpper().StartsWith("NONE") ||
motherboardID.ToUpper().StartsWith("N/A") ||
motherboardID.ToUpper().Contains("SERIAL") ||
motherboardID.ToUpper().Contains("OEM") ||
motherboardID.ToUpper().Contains("AAAAA") ||
motherboardID.ToUpper().Contains("ABCDE") ||
motherboardID.ToUpper().Contains("XXXXX") ||
motherboardID.ToUpper().Contains("NOT") ||
motherboardID.ToUpper().StartsWith("00000")
);
}
CPU ID
private static void FetchCpuIdInternal()
{
try
{
using (ManagementClass mc = new ManagementClass("Win32_Processor"))
{
using (ManagementObjectCollection moc = mc.GetInstances())
{
foreach (ManagementObject mo in moc)
{
if (mo.Properties["UniqueId"] != null && mo.Properties["UniqueId"].Value != null)
{
// only return cpuInfo from first CPU
Trace.WriteLine("CPU ID = " + mo.Properties["UniqueId"].Value.ToString());
_cpuID = mo.Properties["UniqueId"].Value.ToString();
}
mo.Dispose();
}
}
}
}
catch (System.Threading.ThreadAbortException)
{
throw;
}
catch (Exception ex)
{
Trace.TraceWarning("Failed to read CPUID\r\n" + ex.Message);
}
}
第一张卡的MAC地址
private static void FecthMACAddressInternal()
{
try
{
using (ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration"))
{
using (ManagementObjectCollection moc = mc.GetInstances())
{
if (moc != null)
{
foreach (ManagementObject mo in moc)
{
Trace.WriteLine(mo["Index"] + " Mac " + mo["Caption"] + " : " + mo["MacAddress"] + " Enabled " + (bool)mo["IPEnabled"]);
if (string.IsNullOrEmpty(_macAdderss)) // only return MAC Address from first card
{
if ( mo["MacAddress"] != null && mo["IPEnabled"] != null && (bool)mo["IPEnabled"] == true)
{
_macAdderss = mo["MacAddress"].ToString();
}
}
mo.Dispose();
}
}
}
}
}
catch (System.Threading.ThreadAbortException)
{
throw;
}
catch (Exception ex)
{
Trace.TraceWarning("Failed to read DiskID\r\n" + ex.Message);
}
if (_macAdderss != null)
_macAdderss = _macAdderss.Replace(":", "");
}
驱动器序列号
/// <summary>
/// return Volume Serial Number from hard drive
/// </summary>
/// <param name="strDriveLetter">[optional] Drive letter</param>
/// <returns>[string] VolumeSerialNumber</returns>
public static string GetVolumeSerial(char driveLetter)
{
try
{
using (ManagementObject disk = new ManagementObject("win32_logicaldisk.deviceid=\"" + driveLetter + ":\""))
{
if (disk == null)
return null;
disk.Get();
object diskObj = disk["VolumeSerialNumber"];
if (diskObj != null)
return diskObj.ToString();
}
}
catch (System.Threading.ThreadAbortException)
{
throw;
}
catch (Exception ex)
{
Trace.TraceWarning("Failed to read DiskID\r\n" + ex.Message);
}
try
{
uint serialNum, serialNumLength, flags;
StringBuilder volumename = new StringBuilder(256);
StringBuilder fstype = new StringBuilder(256);
bool ok = GetVolumeInformation(driveLetter.ToString() + ":\\", volumename, (uint)volumename.Capacity - 1, out serialNum, out serialNumLength, out flags, fstype, (uint)fstype.Capacity - 1);
if (ok)
{
return string.Format("{0:X4}{1:X4}", serialNum >> 16, serialNum & 0xFFFF);
}
}
catch (System.Threading.ThreadAbortException)
{
throw;
}
catch (Exception ex2)
{
Trace.TraceWarning("Failed to read DiskID\r\n" + ex2.Message);
}
return null;
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern bool GetVolumeInformation(string Volume, StringBuilder VolumeName, uint VolumeNameSize, out uint SerialNumber, out uint SerialNumberLength, out uint flags, StringBuilder fs, uint fs_size);