windows平台下获取网卡MAC地址、硬盘序列号、主板序列号、CPU ID、BIOS序列号

时间:2021-05-13 00:40:29

转自http://blog.csdn.net/jhqin/article/details/5548656,如有侵权,请联系本人删除,谢谢!!

头文件:WMI_DeviceQuery.h

/* ----------------------------------------------------------
文件名称:WMI_DeviceQuery.h 作者:秦建辉 MSN:splashcn@msn.com 版本历史:
V1.4 2010年05月17日
修正了硬盘序列号处理中的错误。现在和EVEREST Ultimate Edition 5.5一致。 V1.3 2010年05月11日
增加了对网卡原生MAC地址的查询。 V1.2 2010年05月05日
增加对硬盘序列号的进一步处理。 V1.1 2010年04月30日
修正微软MSDN例子错误,并增加对虚拟机网卡的判断。 V1.0 2010年04月27日
完成正式版本。 功能描述:
基于WMI获取设备属性:
0:网卡原生MAC地址
1:硬盘序列号
2:主板序列号
3:CPU ID
4:BIOS序列号
5:主板型号
6:网卡当前MAC地址 接口函数:
WMI_DeviceQuery
------------------------------------------------------------ */
#pragma once #include <windows.h> #ifndef MACRO_T_DEVICE_PROPERTY
#define MACRO_T_DEVICE_PROPERTY #define PROPERTY_MAX_LEN 128 // 属性字段最大长度
typedef struct _T_DEVICE_PROPERTY
{
TCHAR szProperty[PROPERTY_MAX_LEN];
} T_DEVICE_PROPERTY;
#endif #define WMI_QUERY_TYPENUM 7 // WMI查询支持的类型数 #ifdef __cplusplus
extern "C"
{
#endif /*
功能:通过WMI获取设备属性
参数说明:
iQueryType:需要查询的设备属性
0:网卡原生MAC地址
1:硬盘序列号
2:主板序列号
3:CPU ID
4:BIOS序列号
5:主板型号
6:网卡当前MAC地址
properties:存储设备属性值
iSize:可存储的最大设备个数
返回值:
-1:不支持的设备属性值
-2:WMI连接失败
-3:不正确的WQL查询语句
>=0:获取的设备个数
*/
INT WMI_DeviceQuery( INT iQueryType, T_DEVICE_PROPERTY *properties, INT iSize ); #ifdef __cplusplus
}
#endif

实现文件:WMI_DeviceQuery.cpp

#include "WMI_DeviceQuery.h"
#include <comutil.h>
#include <Wbemidl.h>
#include <tchar.h>
#include <strsafe.h>
#include <algorithm>
#include <atlconv.h>
#include <ntddndis.h> #pragma comment (lib, "comsuppw.lib")
#pragma comment (lib, "wbemuuid.lib") typedef struct _T_WQL_QUERY
{
CHAR* szSelect; // SELECT语句
WCHAR* szProperty; // 属性字段
} T_WQL_QUERY; // WQL查询语句
const T_WQL_QUERY szWQLQuery[] = {
// 网卡原生MAC地址
"SELECT * FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))",
L"PNPDeviceID", // 硬盘序列号
"SELECT * FROM Win32_DiskDrive WHERE (SerialNumber IS NOT NULL) AND (MediaType LIKE 'Fixed hard disk%')",
L"SerialNumber", // 主板序列号
"SELECT * FROM Win32_BaseBoard WHERE (SerialNumber IS NOT NULL)",
L"SerialNumber", // 处理器ID
"SELECT * FROM Win32_Processor WHERE (ProcessorId IS NOT NULL)",
L"ProcessorId", // BIOS序列号
"SELECT * FROM Win32_BIOS WHERE (SerialNumber IS NOT NULL)",
L"SerialNumber", // 主板型号
"SELECT * FROM Win32_BaseBoard WHERE (Product IS NOT NULL)",
L"Product", // 网卡当前MAC地址
"SELECT * FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))",
L"MACAddress",
}; // 通过“PNPDeviceID”获取网卡原生MAC地址
static BOOL WMI_DoWithPNPDeviceID( const TCHAR *PNPDeviceID, TCHAR *MacAddress, UINT uSize )
{
TCHAR DevicePath[MAX_PATH];
HANDLE hDeviceFile;
BOOL isOK = FALSE; // 生成设备路径名
StringCchCopy( DevicePath, MAX_PATH, TEXT("////.//") );
StringCchCat( DevicePath, MAX_PATH, PNPDeviceID );
StringCchCat( DevicePath, MAX_PATH, TEXT("#{ad498944-762f-11d0-8dcb-00c04fc3358c}") ); // 将“PNPDeviceID”中的“/”替换成“#”,以获得真正的设备路径名
std::replace( DevicePath + 4, DevicePath + 4 + _tcslen(PNPDeviceID), TEXT('//'), TEXT('#') ); // 获取设备句柄
hDeviceFile = CreateFile( DevicePath,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL); if( hDeviceFile != INVALID_HANDLE_VALUE )
{
ULONG dwID;
BYTE ucData[8];
DWORD dwByteRet; // 获取网卡原生MAC地址
dwID = OID_802_3_PERMANENT_ADDRESS;
isOK = DeviceIoControl( hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL );
if( isOK )
{ // 将字节数组转换成16进制字符串
for( DWORD i = 0; i < dwByteRet; i++ )
{
StringCchPrintf( MacAddress + (i << 1), uSize - (i << 1), TEXT("%02X"), ucData[i] );
} MacAddress[dwByteRet << 1] = TEXT('/0'); // 写入字符串结束标记
} CloseHandle( hDeviceFile );
} return isOK;
} static BOOL WMI_DoWithHarddiskSerialNumber( TCHAR *SerialNumber, UINT uSize )
{
UINT iLen;
UINT i; iLen = _tcslen( SerialNumber );
if( iLen == 40 ) // InterfaceType = "IDE"
{ // 需要将16进制编码串转换为字符串
TCHAR ch, szBuf[32];
BYTE b; for( i = 0; i < 20; i++ )
{ // 将16进制字符转换为高4位
ch = SerialNumber[i * 2];
if( (ch >= '0') && (ch <= '9') )
{
b = ch - '0';
}
else if( (ch >= 'A') && (ch <= 'F') )
{
b = ch - 'A' + 10;
}
else if( (ch >= 'a') && (ch <= 'f') )
{
b = ch - 'a' + 10;
}
else
{ // 非法字符
break;
} b <<= 4; // 将16进制字符转换为低4位
ch = SerialNumber[i * 2 + 1];
if( (ch >= '0') && (ch <= '9') )
{
b += ch - '0';
}
else if( (ch >= 'A') && (ch <= 'F') )
{
b += ch - 'A' + 10;
}
else if( (ch >= 'a') && (ch <= 'f') )
{
b += ch - 'a' + 10;
}
else
{ // 非法字符
break;
} szBuf[i] = b;
} if( i == 20 )
{ // 转换成功
szBuf[i] = L'/0';
StringCchCopy( SerialNumber, uSize, szBuf );
iLen = _tcslen( SerialNumber );
}
} // 每2个字符互换位置
for( i = 0; i < iLen; i += 2 )
{
std::swap( SerialNumber[i], SerialNumber[i+1] );
} // 去掉空格
std::remove( SerialNumber, SerialNumber + _tcslen(SerialNumber) + 1, L' ' ); return TRUE;
} static BOOL WMI_DoWithProperty( INT iQueryType, TCHAR *szProperty, UINT uSize )
{
BOOL isOK = TRUE; switch( iQueryType )
{
case 0: // 网卡原生MAC地址
isOK = WMI_DoWithPNPDeviceID( szProperty, szProperty, uSize );
break; case 1: // 硬盘序列号
isOK = WMI_DoWithHarddiskSerialNumber( szProperty, uSize );
break; case 6: // 网卡当前MAC地址
// 去掉冒号
std::remove( szProperty, szProperty + _tcslen(szProperty) + 1, L':' );
break; default:
// 去掉空格
std::remove( szProperty, szProperty + _tcslen(szProperty) + 1, L' ' );
} return isOK;
} // 基于Windows Management Instrumentation(Windows管理规范)
INT WMI_DeviceQuery( INT iQueryType, T_DEVICE_PROPERTY *properties, INT iSize )
{
HRESULT hres;
INT iTotal = 0; // 判断查询类型是否支持
if( (iQueryType < 0) || (iQueryType >= sizeof(szWQLQuery)/sizeof(T_WQL_QUERY)) )
{
return -1; // 查询类型不支持
} // 初始化COM
hres = CoInitializeEx( NULL, COINIT_MULTITHREADED );
if( FAILED(hres) )
{
return -2;
} // 设置COM的安全认证级别
hres = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE,
NULL
);
if( FAILED(hres) )
{
CoUninitialize();
return -2;
} // 获得WMI连接COM接口
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
reinterpret_cast<LPVOID*>(&pLoc)
);
if( FAILED(hres) )
{
CoUninitialize();
return -2;
} // 通过连接接口连接WMI的内核对象名"ROOT//CIMV2"
IWbemServices *pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t( L"ROOT//CIMV2" ),
NULL,
NULL,
NULL,
0,
NULL,
NULL,
&pSvc
);
if( FAILED(hres) )
{
pLoc->Release();
CoUninitialize();
return -2;
} // 设置请求代理的安全级别
hres = CoSetProxyBlanket(
pSvc,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if( FAILED(hres) )
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return -2;
} // 通过请求代理来向WMI发送请求
IEnumWbemClassObject *pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t( szWQLQuery[iQueryType].szSelect ),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator
);
if( FAILED(hres) )
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return -3;
} // 循环枚举所有的结果对象
while( pEnumerator )
{
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0; if( (properties != NULL) && (iTotal >= iSize) )
{
break;
} pEnumerator->Next(
WBEM_INFINITE,
1,
&pclsObj,
&uReturn
); if( uReturn == 0 )
{
break;
} if( properties != NULL )
{ // 获取属性值
VARIANT vtProperty; VariantInit( &vtProperty );
pclsObj->Get( szWQLQuery[iQueryType].szProperty, 0, &vtProperty, NULL, NULL );
StringCchCopy( properties[iTotal].szProperty, PROPERTY_MAX_LEN, W2T(vtProperty.bstrVal) );
VariantClear( &vtProperty ); // 对属性值做进一步的处理
if( WMI_DoWithProperty( iQueryType, properties[iTotal].szProperty, PROPERTY_MAX_LEN ) )
{
iTotal++;
}
}
else
{
iTotal++;
} pclsObj->Release();
} // End While // 释放资源
pEnumerator->Release();
pSvc->Release();
pLoc->Release();
CoUninitialize(); return iTotal;
}

windows平台下获取网卡MAC地址、硬盘序列号、主板序列号、CPU ID、BIOS序列号的更多相关文章

  1. 获取网卡MAC、硬盘序列号、CPU&lowbar;ID、BIOS编号

    抄来的 获取网卡MAC.硬盘序列号.CPU ID.BIOS编号 本文中所有原理及思想均取自网络,有修改.其中获取硬盘序列号.获取CPU编号.获取BIOS编号的原始代码的著作权归各自作者所有. 以下代码 ...

  2. Python 获取 网卡 MAC 地址

    /*********************************************************************** * Python 获取 网卡 MAC 地址 * 说明: ...

  3. Linux&&num;160&semi;下修改网卡MAC地址

    Linux下修改网卡MAC地址 by:授客 QQ:1033553122 例子:修改网卡接口eth0的mac地址 #停用网卡接口,比如eth0 # ifconfig eth0 down #编辑对应的网卡 ...

  4. VC&plus;&plus;获取网卡MAC、硬盘序列号、CPU ID、BIOS编号

    以下代码可以取得系统特征码(网卡MAC.硬盘序列号.CPU ID.BIOS编号) BYTE szSystemInfo[4096]; // 在程序执行完毕后,此处存储取得的系统特征码 UINT uSys ...

  5. 使用WinPcap获取网卡MAC地址

    关键字:WinPcap 网卡 MAC地址 作者:txw1958 在WpdPack_4_1_2\WpdPack\Examples-remote\PacketDriver\GetMacAddress\目录 ...

  6. 转&colon; 通过WMI获取网卡MAC地址、硬盘序列号、主板序列号、CPU ID、BIOS序列号

    最近由于项目的需要,需要在程序中获取机器的硬盘序列号和MAC地址等信息,在C#下,可以很容易的获得这些信息,但是在C++程序中感觉比较麻烦.经过百度,发现很多大虾都是通过WMI来获取这些硬件信息的,网 ...

  7. (转)通过WMI获取网卡MAC地址、硬盘序列号、主板序列号、CPU ID、BIOS序列号

    最近由于项目的需要,需要在程序中获取机器的硬盘序列号和MAC地址等信息,在C#下,可以很容易的获得这些信息,但是在C++程序中感觉比较麻烦.经过百度,发现很多大虾都是通过WMI来获取这些硬件信息的,网 ...

  8. 通过WMI获取网卡MAC地址、硬盘序列号、主板序列号、CPU ID、BIOS序列号

    转载:https://www.cnblogs.com/tlduck/p/5132738.html #define _WIN32_DCOM #include<iostream> #inclu ...

  9. php获取网卡MAC地址源码

    <?php /** 获取网卡的MAC地址原码:目前支持WIN/LINUX系统 获取机器网卡的物理(MAC)地址 **/ class GetMacAddr{ var $return_array = ...

随机推荐

  1. Python 开发轻量级爬虫08

    Python 开发轻量级爬虫 (imooc总结08--爬虫实例--分析目标) 怎么开发一个爬虫?开发一个爬虫包含哪些步骤呢? 1.确定要抓取得目标,即抓取哪些网站的哪些网页的哪部分数据. 本实例确定抓 ...

  2. 在VS中使用类模板出现出现LNK2019&colon; 无法解析的外部符号错误。

    在VS中使用类模板出现出现LNK2019: 无法解析的外部符号错误,应在一个.h文件中完成方法的声明与实现,不要将实现放在cpp文件里,VS貌似不支持类模板分离

  3. &lbrack;drp 5&rsqb; pageModel的建立,实现分页查询

    导读:之前做的分页,一直都是用的easy--UI分页,然后没有系统的整理过,就是知道传几个参数,然后云云.这次,从头到尾总结一下,了了我的这桩心愿.人事系统的重定向工作,一直刺激着我一定要总结总结这个 ...

  4. cos

    Apple过于封闭,没啥朋友,这家伙应该比较高傲,曾仅和Intel,IBM and so on..一起玩过!Google过于开放,狐朋狗友,友人泛滥,殃及ecosystem,弊端已显,祸水将至.COS ...

  5. Stack Overflow 上人气最旺的 10 个 Java 问题

    1. 为什么两个(1927年)时间相减得到一个奇怪的结果? (3623个赞) 如果执行下面的程序,程序解析两个间隔1秒的日期字符串并比较: public static void main(String ...

  6. Python中的eval&lpar;&rpar;、exec&lpar;&rpar;及其相关函数

    刚好前些天有人提到eval()与exec()这两个函数,所以就翻了下Python的文档.这里就来简单说一下这两个函数以及与它们相关的几个函数,如globals().locals()和compile() ...

  7. ASIHTTPRequest异步请求 分类: ios技术 2015-03-01 09&colon;33 48人阅读 评论&lpar;0&rpar; 收藏

    我们运行程序,如果网速很慢,查询的时候会一直黑屏,直到请求结束画面才出现,这样用户体验很不好.因此同步请求一般只是在某个子线 程中使用,而不在主线程中使用.异步请求的用户体验要比同步请求好,因此一般情 ...

  8. Java 通过Xml导出Excel文件,Java Excel 导出工具类,Java导出Excel工具类

    Java 通过Xml导出Excel文件,Java Excel 导出工具类,Java导出Excel工具类 ============================== ©Copyright 蕃薯耀 20 ...

  9. php中获取数据 php&colon;&sol;&sol;input、&dollar;&lowbar;POST与&dollar;GLOBALS&lbrack;&&num;39&semi;HTTP&lowbar;RAW&lowbar;POST&lowbar;DATA&&num;39&semi;&rsqb;三者的区别

    $_POST 只有Coentent-Type的值为application/x-www.form-urlencoded和multipart/form-data两种类型时,$_POST才能获取到数据. $ ...

  10. iOS 中nil,Nil,NULL,NSNull的区别

    类与对象的概念 类是对同一类事物高度的抽象,类中定义了这一类对象所应具有的静态属性(属性)和动态属性(方法). 对象是类的一个实例,是一个具体的事物. 类与对象是抽象与具体的关系. 类其实就是一种数据 ...