|
|
|
|
/* ----------------------------------------------------------
|
|
|
|
|
* 文件名称: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
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 基于WMI获取设备属性值
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="QueryIndex">要查询的属性值索引</param>
|
|
|
|
|
/// <returns>属性值集合</returns>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// QueryIndex其值含义如下:
|
|
|
|
|
/// 0:网卡原生MAC地址(剔除虚拟网卡)
|
|
|
|
|
/// 1:网卡原生MAC地址(剔除虚拟网卡和USB网卡)
|
|
|
|
|
/// 2:硬盘序列号
|
|
|
|
|
/// 3:主板序列号
|
|
|
|
|
/// 4:CPU ID
|
|
|
|
|
/// 5:BIOS序列号
|
|
|
|
|
/// 6:主板型号
|
|
|
|
|
/// 7:网卡当前MAC地址(剔除虚拟网卡)
|
|
|
|
|
/// 8:网卡当前MAC地址(剔除虚拟网卡和USB网卡)
|
|
|
|
|
/// </remarks>
|
|
|
|
|
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<string> DeviceList = new List<string>(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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 查看系统中是否存在指定标识的硬件设备
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="CPUID">处理器标识,可以为空</param>
|
|
|
|
|
/// <param name="HardDiskSerialNumber">硬盘序列号,可以为空</param>
|
|
|
|
|
/// <param name="MacAddress">网卡MAC地址(已剔除虚拟网卡和USB网卡),可以为空</param>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// true:匹配成功
|
|
|
|
|
/// false:匹配失败
|
|
|
|
|
/// </returns>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// 说明:
|
|
|
|
|
/// 对设备标识不区分大小写
|
|
|
|
|
/// 空项不做判断,非空项必须全部满足
|
|
|
|
|
/// </remarks>
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 输出硬件信息到指定INI文件
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="iniFileName">要保存的ini文件名</param>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// true:成功
|
|
|
|
|
/// false:失败
|
|
|
|
|
/// </returns>
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 判断程序是否在VMware虚拟机中运行
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// true:程序是在VMware虚拟机中运行
|
|
|
|
|
/// false:程序不是在VMware虚拟机中运行
|
|
|
|
|
/// </returns>
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取网卡原生物理地址
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="PNPDeviceID">设备ID</param>
|
|
|
|
|
/// <returns>网卡原生物理地址</returns>
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 处理硬盘序列号
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="SerialNumber">硬盘序列号</param>
|
|
|
|
|
/// <returns>处理后的硬盘序列号</returns>
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 版权信息
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static string Copyright { get { return "©秦建辉 http://www.firstsolver.com V20151204R1"; } }
|
|
|
|
|
}
|
|
|
|
|
}
|