最近由于项目的需要,需要在程序中获取机器的硬盘序列号和MAC地址等信息,在C#下,可以很容易的获得这些信息,但是在C++程序中感觉比较麻烦。经过百度,发现很多大虾都是通过WMI来获取这些硬件信息的,网上也有相关的代码,通过实际调试,也发现确实可以通过WMI来获取这些信息。前两天,在网上突然搜到一位大牛写的比较完整的程序,为了以后使用方便,就转载记录一下。同时,也会在大牛的代码中增加一些自己的注释,都是自己在实际使用过程中遇到的问题。

#include "stdafx.h"

#define _WIN32_DCOM

#include "stdafx.h"
#include<iostream>
#include<fstream>
#include<string>
#include "direct.h"
#include <tchar.h>
#include <time.h>
#include <comdef.h>
#include <Wbemidl.h>
#include <conio.h>
#include "atlstr.h"
#include "atlbase.h"
//#include "TcpCtl.h"
//#include "winsock2.h"
//#include "InitDll.h"
using namespace std;

# pragma comment(lib, "wbemuuid.lib")
# pragma comment(lib, "ws2_32.lib")

//通过WMI获取主板号
BOOL ManageWMIBord(char bord[])
{
    HRESULT hres;
    // Step 1:  初始化COM 
    //hres = CoInitializeEx(0, COINIT_MULTITHREADED); //网上的代码都是使用这行语句进行初始化,但是我在实际使用中,发现也可以采用下面的语句进行初始化
    hres = CoInitialize(0);

    //网上的代码是没有注释下面这个判断的,但是实际使用中发现,如果之前已经初始化成功了,在第二次初始化的时候,下面的代码就会导致返回false,所以,实际使用中我就注释掉了
    //if (FAILED(hres))
    //{
    // cout << "Failed to initialize COM library. Error code = 0x" 
    // << hex << hres << endl;
    // return false; // Program has failed.
    //}


    // Step 2:  设置COM的安全认证级别  

    //在实际使用过程中,我发现如果这一步不注释掉的话,程序总是返回false,注释掉之后程序反而可以正常运行,原因未知

    // Note: If you are using Windows 2000, you need to specify -
    // the default authentication credentials for a user by using
    // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
    // parameter of CoInitializeSecurity ------------------------
    ////hres = CoInitializeSecurity(
    //// NULL, 
    //// -1, // COM authentication
    //// NULL, // Authentication services
    //// NULL, // Reserved
    //// RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication 
    //// RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation 
    //// NULL, // Authentication info
    //// EOAC_NONE, // Additional capabilities 
    //// NULL // Reserved
    //// );
    //// 
    ////if (FAILED(hres))
    ////{
    //// cout << "Failed to initialize security. Error code = 0x" 
    //// << hex << hres << endl;
    //// CoUninitialize();
    //// return false; // Program has failed.
    ////}

    // Step 3:  获得WMI连接COM接口  
    IWbemLocator *pLoc = NULL;
    hres = CoCreateInstance(
        CLSID_WbemLocator,
        0,
        CLSCTX_INPROC_SERVER,
        IID_IWbemLocator, (LPVOID *)&pLoc);

    if (FAILED(hres))
    {
        cout << "Failed to create IWbemLocator object."
            << " Err code = 0x"
            << hex << hres << endl;
        CoUninitialize();
        return false; // Program has failed.
    }


    // Step 4:  通过连接接口连接WMI的内核对象名"ROOT//CIMV2"  
    IWbemServices *pSvc = NULL;

    hres = pLoc->ConnectServer(

        _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
        NULL, // User name. NULL = current user
        NULL, // User password. NULL = current
        0, // Locale. NULL indicates current
        NULL, // Security flags.
        0, // Authority (e.g. Kerberos)
        0, // Context object 
        &pSvc // pointer to IWbemServices proxy
        );

    if (FAILED(hres))
    {
        cout << "Could not connect. Error code = 0x"
            << hex << hres << endl;
        pLoc->Release();
        CoUninitialize();
        return false; // Program has failed.
    }
    //cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;

    // Step 5:  设置请求代理的安全级别   
    hres = CoSetProxyBlanket(
        pSvc, // Indicates the proxy to set
        RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
        RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
        NULL, // Server principal name 
        RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx 
        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
        NULL, // client identity
        EOAC_NONE // proxy capabilities 
        );
    if (FAILED(hres))
    {
        cout << "Could not set proxy blanket. Error code = 0x"
            << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return false; // Program has failed.
    }
    // Step 6: 通过请求代理来向WMI发送请求----
    // For example, get the name of the operating system
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(
        bstr_t("WQL"),
        //bstr_t("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = 'TRUE'"), 
        bstr_t("SELECT * FROM Win32_BaseBoard"),//只需要通过修改这里的查询语句,就可以实现对MAC地址等其他信息的查询
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
        NULL,
        &pEnumerator);

    if (FAILED(hres))
    {
        cout << "Query for Network Adapter Configuration failed."
            << " Error code = 0x"
            << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return false; // Program has failed.
    }


    // Step 7:  循环枚举所有的结果对象

    IWbemClassObject *pclsObj;
    ULONG uReturn = 0;

    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
            &pclsObj, &uReturn);
        if (0 == uReturn)
        {
            break;
        }
        VARIANT vtProp;
        VariantInit(&vtProp);

        hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);//查询不同的硬件信息,除了修改上面的查询语句,这里的字段也要修改

        if (!FAILED(hr))
        {
            CW2A tmpstr1(vtProp.bstrVal);
            strcpy_s(bord, 200, tmpstr1);//这里的200是可调的,自己根据实际情况设置,但是肯定不能大于bord的长度
            //cout << "BordSN:" << sn << endl;

        }

        VariantClear(&vtProp);
    }//end while

    // 释放资源  
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    pclsObj->Release();
    CoUninitialize();
    return true; // Program successfully completed.

}

//附: 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",

    //当前机器的型号和厂商

    "SELECT * FROM Win32_computersystem",

    L"Manufacturer", L"Model"
}

 

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。 ,

   最近由于项目的需要,需要在程序中获取机器的硬盘序列号和MAC地址等信息,在C#下,可以很容易的获得这些信息,但是在C++程序中感觉比较麻烦。经过百度,发现很多大虾都是通过WMI来获取这些硬件信息的,网上也有相关的代码,通过实际调试,也发现确实可以通过WMI来获取这些信息。前两天,在网上突然搜到一位大牛写的比较完整的程序,为了以后使用方便,就转载记录一下。同时,也会在大牛的代码中增加一些自己的注释,都是自己在实际使用过程中遇到的问题。

#include "stdafx.h"

#define _WIN32_DCOM

#include "stdafx.h"
#include<iostream>
#include<fstream>
#include<string>
#include "direct.h"
#include <tchar.h>
#include <time.h>
#include <comdef.h>
#include <Wbemidl.h>
#include <conio.h>
#include "atlstr.h"
#include "atlbase.h"
//#include "TcpCtl.h"
//#include "winsock2.h"
//#include "InitDll.h"
using namespace std;

# pragma comment(lib, "wbemuuid.lib")
# pragma comment(lib, "ws2_32.lib")

//通过WMI获取主板号
BOOL ManageWMIBord(char bord[])
{
    HRESULT hres;
    // Step 1:  初始化COM 
    //hres = CoInitializeEx(0, COINIT_MULTITHREADED); //网上的代码都是使用这行语句进行初始化,但是我在实际使用中,发现也可以采用下面的语句进行初始化
    hres = CoInitialize(0);

    //网上的代码是没有注释下面这个判断的,但是实际使用中发现,如果之前已经初始化成功了,在第二次初始化的时候,下面的代码就会导致返回false,所以,实际使用中我就注释掉了
    //if (FAILED(hres))
    //{
    // cout << "Failed to initialize COM library. Error code = 0x" 
    // << hex << hres << endl;
    // return false; // Program has failed.
    //}


    // Step 2:  设置COM的安全认证级别  

    //在实际使用过程中,我发现如果这一步不注释掉的话,程序总是返回false,注释掉之后程序反而可以正常运行,原因未知

    // Note: If you are using Windows 2000, you need to specify -
    // the default authentication credentials for a user by using
    // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
    // parameter of CoInitializeSecurity ------------------------
    ////hres = CoInitializeSecurity(
    //// NULL, 
    //// -1, // COM authentication
    //// NULL, // Authentication services
    //// NULL, // Reserved
    //// RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication 
    //// RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation 
    //// NULL, // Authentication info
    //// EOAC_NONE, // Additional capabilities 
    //// NULL // Reserved
    //// );
    //// 
    ////if (FAILED(hres))
    ////{
    //// cout << "Failed to initialize security. Error code = 0x" 
    //// << hex << hres << endl;
    //// CoUninitialize();
    //// return false; // Program has failed.
    ////}

    // Step 3:  获得WMI连接COM接口  
    IWbemLocator *pLoc = NULL;
    hres = CoCreateInstance(
        CLSID_WbemLocator,
        0,
        CLSCTX_INPROC_SERVER,
        IID_IWbemLocator, (LPVOID *)&pLoc);

    if (FAILED(hres))
    {
        cout << "Failed to create IWbemLocator object."
            << " Err code = 0x"
            << hex << hres << endl;
        CoUninitialize();
        return false; // Program has failed.
    }


    // Step 4:  通过连接接口连接WMI的内核对象名"ROOT//CIMV2"  
    IWbemServices *pSvc = NULL;

    hres = pLoc->ConnectServer(

        _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
        NULL, // User name. NULL = current user
        NULL, // User password. NULL = current
        0, // Locale. NULL indicates current
        NULL, // Security flags.
        0, // Authority (e.g. Kerberos)
        0, // Context object 
        &pSvc // pointer to IWbemServices proxy
        );

    if (FAILED(hres))
    {
        cout << "Could not connect. Error code = 0x"
            << hex << hres << endl;
        pLoc->Release();
        CoUninitialize();
        return false; // Program has failed.
    }
    //cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;

    // Step 5:  设置请求代理的安全级别   
    hres = CoSetProxyBlanket(
        pSvc, // Indicates the proxy to set
        RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
        RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
        NULL, // Server principal name 
        RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx 
        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
        NULL, // client identity
        EOAC_NONE // proxy capabilities 
        );
    if (FAILED(hres))
    {
        cout << "Could not set proxy blanket. Error code = 0x"
            << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return false; // Program has failed.
    }
    // Step 6: 通过请求代理来向WMI发送请求----
    // For example, get the name of the operating system
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(
        bstr_t("WQL"),
        //bstr_t("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = 'TRUE'"), 
        bstr_t("SELECT * FROM Win32_BaseBoard"),//只需要通过修改这里的查询语句,就可以实现对MAC地址等其他信息的查询
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
        NULL,
        &pEnumerator);

    if (FAILED(hres))
    {
        cout << "Query for Network Adapter Configuration failed."
            << " Error code = 0x"
            << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return false; // Program has failed.
    }


    // Step 7:  循环枚举所有的结果对象

    IWbemClassObject *pclsObj;
    ULONG uReturn = 0;

    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
            &pclsObj, &uReturn);
        if (0 == uReturn)
        {
            break;
        }
        VARIANT vtProp;
        VariantInit(&vtProp);

        hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);//查询不同的硬件信息,除了修改上面的查询语句,这里的字段也要修改

        if (!FAILED(hr))
        {
            CW2A tmpstr1(vtProp.bstrVal);
            strcpy_s(bord, 200, tmpstr1);//这里的200是可调的,自己根据实际情况设置,但是肯定不能大于bord的长度
            //cout << "BordSN:" << sn << endl;

        }

        VariantClear(&vtProp);
    }//end while

    // 释放资源  
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    pclsObj->Release();
    CoUninitialize();
    return true; // Program successfully completed.

}

//附: 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",

    //当前机器的型号和厂商

    "SELECT * FROM Win32_computersystem",

    L"Manufacturer", L"Model"
}

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄