alibabamama 发表于 2017-7-7 18:17:26

使用WMI编程获取主机硬件信息(CPU_ID,硬盘、主板、BIOS序列号,Mac地址)

  最近在公司实习,有个应用需要获取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;                  //CPU序列号
   char BaseBoardID;         //主板ID
   char SystemDiskID;      //系统所在硬盘的序列号
   char BIOSID;                   //BIOS序列号
   char MacAddress;             //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 = data;
         }
   }
   data = '\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;
   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函数啦~
页: [1]
查看完整版本: 使用WMI编程获取主机硬件信息(CPU_ID,硬盘、主板、BIOS序列号,Mac地址)