312次浏览

C/C++调用WMI获取硬盘CPU序列号网卡地址

最近要做个简单的网络验证, 需要取硬件的一些信息, 例如CPU序列号, 硬盘序列号, MAC地址, OS名称等等, 折腾了一天终于搞定了并且做了些简单封装, 先放个截图

stdafx.h

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//

#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>



// TODO:  在此处引用程序需要的其他头文件
#include<Windows.h>
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")


#include <iostream>
#include<string>
#include<vector>
using namespace std;

main.cpp

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"


class system_info
{
public:
	~system_info();
	system_info(wchar_t* WMI_Namespace = L"ROOT\\CIMV2");
	void Get_CpuId(string& dest);
	void Get_DiskDriveId(string& dest);
	void Get_MacAddress(string& dest);
	void Get_OsName(string& dest);
private:
	IWbemServices* pSvc; //接收指向绑定到指定名称空间的IWbemServices对象的指针
	IWbemLocator* pLoc; //接收CoCreateInstance 创建的实例指针
	bool ExecQuery(char* strQueryLanguage, char* strQuery, IEnumWbemClassObject** pEnumerator);
};

system_info::~system_info()
{
	pSvc->Release();
	pLoc->Release();
}

system_info::system_info(wchar_t *WMI_Namespace)
{
	pSvc = NULL;
	pLoc = NULL;


	HRESULT 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();
	}



	//使用创建好的实例进行连接, 连接成功后的指针保存在psvc
	hres = pLoc->ConnectServer(
		_bstr_t(WMI_Namespace), // 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 (for example, 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();
	}


	// Step 5: --------------------------------------------------
	// Set security levels on the proxy -------------------------

	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();
	}


}

bool system_info::ExecQuery(char* strQueryLanguage, char* strQuery, IEnumWbemClassObject** pEnumerator)
{
	HRESULT hres = pSvc->ExecQuery(
		bstr_t(strQueryLanguage),
		bstr_t(strQuery),
		WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
		NULL,
		pEnumerator);

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

	return true;
}

void system_info::Get_CpuId(string& dest)
{
	IEnumWbemClassObject* pEnumerator=NULL;//存放查询语句执行结果
	ExecQuery("WQL", "SELECT * FROM Win32_Processor WHERE (ProcessorId IS NOT NULL)", &pEnumerator);


	IWbemClassObject *pclsObj = NULL;
	ULONG uReturn = 0;


	while (pEnumerator)
	{
		//  此方法将查询返回的数据对象传递给IWbemClassObject指针。
		HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
			&pclsObj, &uReturn);

		if (0 == uReturn)
		{
			break;
		}

		VARIANT vtProp;

		// Get the value of the Name property
		hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0);
		dest = (_bstr_t)vtProp.bstrVal;

		VariantClear(&vtProp);

		pclsObj->Release();
	}

	pEnumerator->Release();
}

void system_info::Get_DiskDriveId(string & dest)
{
	IEnumWbemClassObject* pEnumerator = NULL;//存放查询语句执行结果
	ExecQuery("WQL", "SELECT * FROM Win32_DiskDrive WHERE (SerialNumber IS NOT NULL)", &pEnumerator);


	IWbemClassObject *pclsObj = NULL;
	ULONG uReturn = 0;

	while (pEnumerator)
	{
		//  此方法将查询返回的数据对象传递给IWbemClassObject指针。
		HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
			&pclsObj, &uReturn);

		if (0 == uReturn)
		{
			break;
		}

		VARIANT vtProp;

		// Get the value of the Name property
		hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
		dest = (_bstr_t)vtProp.bstrVal;

		VariantClear(&vtProp);

		pclsObj->Release();

		//这里直接跳出, 只获取第一个硬盘的序列号
		break;
	}

	pEnumerator->Release();
}

void system_info::Get_MacAddress(string& dest)
{
	IEnumWbemClassObject* pEnumerator = NULL;//存放查询语句执行结果
	ExecQuery("WQL", "SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True", &pEnumerator);

	IWbemClassObject *pclsObj = NULL;
	ULONG uReturn = 0;
	vector<string> MACAddress;

	while (pEnumerator)
	{
		//  此方法将查询返回的数据对象传递给IWbemClassObject指针。
		HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
			&pclsObj, &uReturn);

		if (0 == uReturn)
		{
			break;
		}

		VARIANT vtProp;
		pclsObj->Get(L"MACAddress", 0, &vtProp, 0, 0);
		MACAddress.push_back((string)_bstr_t(vtProp.bstrVal));

		


		VariantClear(&vtProp);

		pclsObj->Release();
	}

	if (MACAddress.size() >= 1)
	{
		dest = MACAddress[0];//返回第一个网卡地址
	}

	pEnumerator->Release();
}

void system_info::Get_OsName(string & dest)
{
	IEnumWbemClassObject* pEnumerator = NULL;//存放查询语句执行结果
	ExecQuery("WQL", "SELECT * FROM Win32_OperatingSystem WHERE (Name IS NOT NULL)", &pEnumerator);


	IWbemClassObject *pclsObj = NULL;
	ULONG uReturn = 0;

	while (pEnumerator)
	{
		//  此方法将查询返回的数据对象传递给IWbemClassObject指针。
		HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
			&pclsObj, &uReturn);

		if (0 == uReturn)
		{
			break;
		}

		VARIANT vtProp;

		// Get the value of the Name property
		hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
		dest = (_bstr_t)vtProp.bstrVal;

		VariantClear(&vtProp);

		pclsObj->Release();

		//这里直接跳出, 只获取第一个硬盘的序列号
		break;
	}

	pEnumerator->Release();
}

int main(int argc, char **argv)
{
	CoInitializeEx(0, COINIT_MULTITHREADED);
	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
	);

	string CpuId, DiskDriveId, MACAddress, OsName;

	system_info *sys= new system_info;

	sys->Get_DiskDriveId(DiskDriveId);
	sys->Get_MacAddress(MACAddress);
	sys->Get_CpuId(CpuId);
	sys->Get_OsName(OsName);

	cout << "OS Name: " << OsName << endl;
	cout << "CPU: " << CpuId << endl;
	cout << "MAC地址: " << MACAddress << endl;
	cout << "硬盘sn: " << DiskDriveId << endl;

	delete sys; //赶在CoUninitialize()执行前释放wmi对象


	CoUninitialize();
	return 0;
}

WMI编程参考资料:

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/9d7a00a4-6bcd-444b-a0e2-a49e2b19e350/please-i-need-a-c-routine-with-which-i-can-retrieve-the-hard-disk-serial-number-using-wmi?forum=windowssdk

https://docs.microsoft.com/zh-cn/windows/win32/wmisdk/example–getting-wmi-data-from-the-local-computer?redirectedfrom=MSDN

http://www.doc88.com/p-3866623931452.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注