|
最近在公司实习,有个应用需要获取windows主机的一些硬件信息,在网上查阅了一些资料,大部分都是使用WMI编程来实现的。
因此小菜鸟自己也用WMI实现了一下,封装为函数GetUserInfo(),具体代码如下:
头文件UserInfo.h:
#pragma once
#include "stdafx.h"
#define _WIN32_DCOM
#include <comdef.h>
#include <Wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")
using namespace std;
typedef struct UserInfo_t
{
char CpuID[20]; //CPU序列号
char BaseBoardID[256]; //主板ID
char SystemDiskID[256]; //系统所在硬盘的序列号
char BIOSID[20]; //BIOS序列号
char MacAddress[20]; //MAC地址
}UserInfo;
int GetUserInfo(UserInfo &info);
View Code 源代码GetUerInfo.cpp:
#include "UserInfo.h"
#include <windows.h>
void Trims(char* data) //去掉字符串中的空格
{
int i=-1,j=0;
int ch = ' ';
while(data[++i] != '\0')
{
if(data != ch)
{
data[j++] = data;
}
}
data[j] = '\0';
}
int GetUserInfo(UserInfo &info)
{
HRESULT hres;
memset(&info,0x00,sizeof(UserInfo));
CoUninitialize();
hres = CoInitializeEx(0, COINIT_MULTITHREADED); //第二个参数设置当前线程的并发模式为多线程
//hres = CoInitializeEx(0,COINIT_APARTMENTTHREADED); //并发模式为单线程(即只能在单线程函数中调用GetUserInfo())
if (FAILED(hres))
{
return -1;
}
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;
}
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
CoUninitialize();
return -3;
}
IWbemServices *pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if (FAILED(hres))
{
pLoc->Release();
CoUninitialize();
return -4;
}
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 -5;
}
//获取CPU序列号
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM win32_Processor"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return -6;
}
IWbemClassObject *pclsObj;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
wcstombs(info.CpuID,vtProp.bstrVal,18);
VariantClear(&vtProp);
pclsObj->Release();
}
//获取主板ID
pEnumerator->Release();
pEnumerator=NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_BaseBoard"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return -7;
}
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
wcstombs(info.BaseBoardID,vtProp.bstrVal,20);
VariantClear(&vtProp);
pclsObj->Release();
}
//获取系统所在硬盘的ID
int diskIndex = 0;
pEnumerator->Release();
pEnumerator=NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_DiskPartition WHERE Bootable = TRUE"), //查找启动盘
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return -8;
}
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
hr = pclsObj->Get(L"DiskIndex", 0, &vtProp, 0, 0);
diskIndex = vtProp.intVal;
VariantClear(&vtProp);
pclsObj->Release();
}
//根据系统所在硬盘的ID查询序列号
char index[10];
string strQuery = "SELECT * FROM Win32_DiskDrive WHERE Index = ";
itoa(diskIndex,index,10);
string indexStr(index);
strQuery += indexStr;
pEnumerator->Release();
pEnumerator=NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t(strQuery.c_str()),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return -8;
}
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
wcstombs(info.SystemDiskID,vtProp.bstrVal,20);
Trims(info.SystemDiskID);
VariantClear(&vtProp);
pclsObj->Release();
}
//获取BIOS序列号
pEnumerator->Release();
pEnumerator=NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_BIOS"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return -9;
}
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
wcstombs(info.BIOSID,vtProp.bstrVal,20);
VariantClear(&vtProp);
pclsObj->Release();
}
//获取本地连接的MAC地址
pEnumerator->Release();
pEnumerator=NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return -10;
}
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
hr = pclsObj->Get(L"Description", 0, &vtProp, 0, 0);
string des = (_bstr_t)vtProp.bstrVal;
if(strstr(des.c_str(),"Ethernet Connection") != NULL)
{
hr = pclsObj->Get(L"MacAddress", 0, &vtProp, 0, 0);
wcstombs(info.MacAddress,vtProp.bstrVal,20);
}
VariantClear(&vtProp);
pclsObj->Release();
}
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
return 0;
}
View Code 在我自己的win7电脑(64位)上测试过,可以获取到想要的硬件信息,但是在公司另一台win7电脑(32位)上,只获取到cpu_id字段,其他几个字段为空。
出现这样的问题,我也不太清楚是由于WMI编程代码的问题,还是电脑主机的问题。如果有码友看出我代码中的问题,欢迎留言指教~
另外查阅了一些资料,有人说可以用DeviceIoControl函数来实现获取主机硬件信息,所以我现在要去研究DeviceIoControl函数啦~ |
|