/* ---------------------------------------------------------- * 文件名称:HWiNFO.cs * * 作者:秦建辉 * * 微信:splashcn * * 博客:http://www.firstsolver.com/wordpress/ * * 开发环境: * Visual Studio V2013 * .NET Framework 4 Client Profile * * 版本历史: * V2.1 2016年12月29日 * 修正硬盘序列号长度为奇数时的处理错误 * * V2.0 2015年12月04日 * 增加对VMware虚拟机的判断。虚拟机可以伪造任意网卡MAC地址 * 在WDK中实现0权限获取硬盘序列号 * * V1.0 2014年04月06日 * 实现基于WMI获取网卡原生MAC地址、硬盘序列号、CPU ID * 实现基于WDK获取网卡原生MAC地址 * 实现结合设备安装类GUID和设备接口类GUID获取设备VIDPID ------------------------------------------------------------ */ using System; using System.Collections.Generic; using System.Management; using System.Runtime.InteropServices; using System.Text; namespace POSV.HWiNFO { public static partial class HWiNFO { /// /// 基于WMI获取设备属性值 /// /// 要查询的属性值索引 /// 属性值集合 /// /// QueryIndex其值含义如下: /// 0:网卡原生MAC地址(剔除虚拟网卡) /// 1:网卡原生MAC地址(剔除虚拟网卡和USB网卡) /// 2:硬盘序列号 /// 3:主板序列号 /// 4:CPU ID /// 5:BIOS序列号 /// 6:主板型号 /// 7:网卡当前MAC地址(剔除虚拟网卡) /// 8:网卡当前MAC地址(剔除虚拟网卡和USB网卡) /// public static string[] WMI_DeviceQuery(int QueryIndex) { // 确定查询语句和属性名称 string Command; string PropertyName; switch (QueryIndex) { case 0: // 网卡原生MAC地址(剔除虚拟网卡) Command = "SELECT PNPDeviceID FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))"; PropertyName = "PNPDeviceID"; break; case 1: // 网卡原生MAC地址(剔除虚拟网卡和USB网卡) Command = "SELECT PNPDeviceID FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%')) AND (NOT (PNPDeviceID LIKE 'USB%'))"; PropertyName = "PNPDeviceID"; break; case 2: // 硬盘序列号 Command = "SELECT SerialNumber FROM Win32_DiskDrive WHERE (SerialNumber IS NOT NULL) AND (MediaType LIKE 'Fixed hard disk%')"; PropertyName = "SerialNumber"; break; case 3: // 主板序列号 Command = "SELECT SerialNumber FROM Win32_BaseBoard WHERE (SerialNumber IS NOT NULL)"; PropertyName = "SerialNumber"; break; case 4: // 处理器ID Command = "SELECT ProcessorId FROM Win32_Processor WHERE (ProcessorId IS NOT NULL)"; PropertyName = "ProcessorId"; break; case 5: // BIOS序列号 Command = "SELECT SerialNumber FROM Win32_BIOS WHERE (SerialNumber IS NOT NULL)"; PropertyName = "SerialNumber"; break; case 6: // 主板型号 Command = "SELECT Product FROM Win32_BaseBoard WHERE (Product IS NOT NULL)"; PropertyName = "Product"; break; case 7: // 网卡当前MAC地址(剔除虚拟网卡) Command = "SELECT MACAddress FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))"; PropertyName = "MACAddress"; break; case 8: // 网卡当前MAC地址(剔除虚拟网卡和USB网卡) Command = "SELECT MACAddress FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%')) AND (NOT (PNPDeviceID LIKE 'USB%'))"; PropertyName = "MACAddress"; break; default: return null; } // 进行WMI查询 List DeviceList = new List(16); ManagementObjectCollection DevicePropertyCollection = new ManagementObjectSearcher(Command).Get(); if (DevicePropertyCollection != null) { foreach (ManagementObject DeviceProperty in DevicePropertyCollection) { string Property = (string)DeviceProperty[PropertyName]; // 获取属性值 if (!DeviceList.Contains(Property)) DeviceList.Add(Property); // 去掉重复值 } } if (DeviceList.Count == 0) return null; switch (QueryIndex) { case 0: // 网卡原生MAC地址 case 1: // 网卡原生MAC地址(剔除USB网卡) for (int i = DeviceList.Count - 1; i >= 0; i--) { string PermanentAddress = GetPermanentAddressByDeviceId(DeviceList[i]); if (PermanentAddress == null) { // 移除当前项 DeviceList.RemoveAt(i); } else { // 替换为网卡原生MAC地址 DeviceList[i] = PermanentAddress; } } break; case 2: // 硬盘序列号 for (int i = DeviceList.Count - 1; i >= 0; i--) { DeviceList[i] = ProcessHardDiskSerialNumber(DeviceList[i]); } break; case 7: // 网卡当前MAC地址 case 8: // 网卡当前MAC地址(剔除USB网卡) for (int i = DeviceList.Count - 1; i >= 0; i--) { // 去掉冒号 DeviceList[i] = DeviceList[i].Replace(":", ""); } break; default: break; } return DeviceList.ToArray(); } /// /// 查看系统中是否存在指定标识的硬件设备 /// /// 处理器标识,可以为空 /// 硬盘序列号,可以为空 /// 网卡MAC地址(已剔除虚拟网卡和USB网卡),可以为空 /// /// true:匹配成功 /// false:匹配失败 /// /// /// 说明: /// 对设备标识不区分大小写 /// 空项不做判断,非空项必须全部满足 /// public static bool WMI_DeviceMatch(string CPUID, string HardDiskSerialNumber, string MacAddress) { // CPU ID if (!string.IsNullOrEmpty(CPUID)) { string[] Properties = WMI_DeviceQuery(4); if (Properties == null) return false; bool IsExist = false; foreach (string Item in Properties) { if (CPUID.Equals(Item, StringComparison.OrdinalIgnoreCase)) { IsExist = true; break; } } if (!IsExist) return false; } // 硬盘序列号 if (!string.IsNullOrEmpty(HardDiskSerialNumber)) { string[] Properties = WMI_DeviceQuery(2); if (Properties == null) return false; bool IsExist = false; foreach (string Item in Properties) { if (HardDiskSerialNumber.Equals(Item, StringComparison.OrdinalIgnoreCase)) { IsExist = true; break; } } if (!IsExist) return false; } // 网卡原生MAC地址 if (!string.IsNullOrEmpty(MacAddress)) { string[] Properties = WMI_DeviceQuery(1); if (Properties == null) return false; bool IsExist = false; foreach (string Item in Properties) { if (MacAddress.Equals(Item, StringComparison.OrdinalIgnoreCase)) { IsExist = true; break; } } if (!IsExist) return false; } // 判断程序是否是在VMware虚拟机中运行 if (WMI_IsVMware()) return false; else return true; } /// /// 输出硬件信息到指定INI文件 /// /// 要保存的ini文件名 /// /// true:成功 /// false:失败 /// public static bool WMI_DeviceInfoPrint(string iniFileName) { if (string.IsNullOrEmpty(iniFileName)) return false; LINQToINI iniFile = new LINQToINI(); // 网卡原生MAC地址 string[] Properties = WMI_DeviceQuery(1); if (Properties != null) { for (int i = 0; i < Properties.Length; i++) { iniFile.WriteProfileString("MacAddress", i.ToString(), Properties[i]); } } // 硬盘序列号 Properties = WMI_DeviceQuery(2); if (Properties != null) { for (int i = 0; i < Properties.Length; i++) { iniFile.WriteProfileString("HardDiskSerialNumber", i.ToString(), Properties[i]); } } // CPU ID Properties = WMI_DeviceQuery(4); if (Properties != null) { for (int i = 0; i < Properties.Length; i++) { iniFile.WriteProfileString("CPUID", i.ToString(), Properties[i]); } } iniFile.Save(iniFileName); return true; } /// /// 判断程序是否在VMware虚拟机中运行 /// /// /// true:程序是在VMware虚拟机中运行 /// false:程序不是在VMware虚拟机中运行 /// public static bool WMI_IsVMware() { string Command = "SELECT Model FROM Win32_DiskDrive WHERE (MediaType LIKE 'Fixed hard disk%')"; ManagementObjectCollection DevicePropertyCollection = new ManagementObjectSearcher(Command).Get(); if (DevicePropertyCollection != null) { foreach (ManagementObject DeviceProperty in DevicePropertyCollection) { string Model = (string)DeviceProperty["Model"]; if (!string.IsNullOrEmpty(Model) && (Model.IndexOf("VMware") >= 0)) { return true; } break; // 只需要判断第一个硬盘 } } return false; } /// /// 获取网卡原生物理地址 /// /// 设备ID /// 网卡原生物理地址 private static string GetPermanentAddressByDeviceId(string PNPDeviceID) { // 生成设备路径名 string DevicePath = @"\\.\" + PNPDeviceID.Replace('\\', '#') + "#{ad498944-762f-11d0-8dcb-00c04fc3358c}"; // 获取设备句柄 IntPtr DeviceHandle = Kernel32.CreateFile(DevicePath, NativeFileAccess.SPECIAL, NativeFileShare.FILE_SHARE_READ | NativeFileShare.FILE_SHARE_WRITE, IntPtr.Zero, NativeFileMode.OPEN_EXISTING, IntPtr.Zero, IntPtr.Zero); if (DeviceHandle != Kernel32.INVALID_HANDLE_VALUE) { byte[] ucData = new byte[8]; int nBytesReturned; // 获取原生MAC地址 const int IOCTL_NDIS_QUERY_GLOBAL_STATS = 0x00170002; uint OID_802_3_PERMANENT_ADDRESS = 0x01010101; bool isOK = Kernel32.DeviceIoControl(DeviceHandle, IOCTL_NDIS_QUERY_GLOBAL_STATS, ref OID_802_3_PERMANENT_ADDRESS, Marshal.SizeOf(OID_802_3_PERMANENT_ADDRESS), ucData, ucData.Length, out nBytesReturned, IntPtr.Zero); Kernel32.CloseHandle(DeviceHandle); if (isOK) { StringBuilder sb = new StringBuilder(nBytesReturned << 1); for (int i = 0; i < nBytesReturned; i++) { sb.Append(ucData[i].ToString("X2")); } return sb.ToString(); } } return null; } /// /// 处理硬盘序列号 /// /// 硬盘序列号 /// 处理后的硬盘序列号 private static string ProcessHardDiskSerialNumber(string SerialNumber) { StringBuilder sb; if (SerialNumber.Length == 40) // InterfaceType = "IDE" { sb = new StringBuilder(20); for (int i = 0; i < 40; i += 2) { // 将16进制表示的字符转换为Unicode字符 sb.Append(Convert.ToChar(Convert.ToInt32(SerialNumber.Substring(i, 2), 16))); } } else { sb = new StringBuilder(SerialNumber); } if (sb.Length % 2 == 0) { // 每2个字符互换位置 for (int i = 0; i < sb.Length; i += 2) { char ch = sb[i]; sb[i] = sb[i + 1]; sb[i + 1] = ch; } } sb.Replace(" ", ""); // 去掉空格 return sb.ToString(); } /// /// 版权信息 /// public static string Copyright { get { return "©秦建辉 http://www.firstsolver.com V20151204R1"; } } } }