封装WMI查询的简单类CWMIUtil
头文件WMIUtil.h
#pragma once#includeclass CWMIUtil{public: CWMIUtil(void); virtual ~CWMIUtil(void); private: // 禁止复制和赋值 CWMIUtil(const CWMIUtil&); CWMIUtil& operator = (const CWMIUtil&); public: DWORD GetErrorCode() const; const TCHAR *GetErrorInfo() const;private: void SetErrorCode(const DWORD dwErrorCode); void SetErrorInfo(const TCHAR *szFormat, ...); public: BOOL Init(); BOOL ConnectServer(const TCHAR *szServer = TEXT("ROOT\\CIMV2")); BOOL ExecQuery(const TCHAR *szQuerySql); BOOL Next(); BOOL GetProperty(const TCHAR *szValueName, TCHAR *szValue, const DWORD dwSizeInByte); private: DWORD m_dwErrorCode; CString m_csErrorInfo; private: BOOL m_bInitComSuccess; private: IWbemLocator *m_pLoc; IWbemServices *m_pSvc; IEnumWbemClassObject* m_pEnumerator; IWbemClassObject *m_pCurObj;};
源文件WMIUtil.cpp
#include "stdafx.h"#include "WMIUtil.h" #define _WIN32_DCOM#include# pragma comment(lib, "wbemuuid.lib") CWMIUtil::CWMIUtil(void) : m_dwErrorCode(0), m_csErrorInfo(TEXT("")), m_bInitComSuccess(FALSE) , m_pLoc(NULL), m_pSvc(NULL), m_pEnumerator(NULL), m_pCurObj(NULL){} CWMIUtil::~CWMIUtil(void){ try { // 释放对象 if (m_pCurObj) { m_pCurObj->Release(); } if (m_pEnumerator) { m_pEnumerator->Release(); } if (m_pSvc) { m_pSvc->Release(); } if (m_pLoc) { m_pLoc->Release(); } if (m_bInitComSuccess) { CoUninitialize(); } } catch (_com_error &e) { // COM exception } catch (CException &e) { // MFC exception } catch (...) { // all exception }} DWORD CWMIUtil::GetErrorCode() const{ return m_dwErrorCode;} const TCHAR *CWMIUtil::GetErrorInfo() const{ return m_csErrorInfo.GetString();} void CWMIUtil::SetErrorCode(const DWORD dwErrorCode){ m_dwErrorCode = dwErrorCode;} void CWMIUtil::SetErrorInfo(const TCHAR *szFormat, ...){ int nSize = 1024; TCHAR *szBuf = new TCHAR[nSize]; ZeroMemory(szBuf, nSize * sizeof(TCHAR)); try { va_list args; va_start(args, szFormat); nSize = _vsntprintf_s(szBuf, nSize, _TRUNCATE, szFormat, args); if (nSize < 0) { m_csErrorInfo = TEXT("SetErrorInfo error, _vsntprintf_s return size less than 0"); } else { m_csErrorInfo = szBuf; } } catch (...) { m_csErrorInfo = TEXT("SetErrorInfo error, _vsntprintf_s exception"); } delete [] szBuf;} BOOL CWMIUtil::Init(){ BOOL bReturn = FALSE; do { // 初始化COM接口 HRESULT hres = CoInitializeEx(0, COINIT_APARTMENTTHREADED); if (FAILED(hres)) { SetErrorCode(hres); SetErrorInfo(TEXT("Failed to initialize COM library. Error code = 0x%x"), hres); break; } hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT , RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); if (FAILED(hres) && RPC_E_TOO_LATE != hres) { SetErrorCode(hres); SetErrorInfo(TEXT("Failed to initialize security. Error code = 0x%x"), hres); break; } m_bInitComSuccess = TRUE; bReturn = TRUE; } while (FALSE); return bReturn;} BOOL CWMIUtil::ConnectServer(const TCHAR *szServer /* = TEXT("ROOT\\CIMV2") */){ // 有效性判断 if (!m_bInitComSuccess) { SetErrorCode(1); SetErrorInfo(TEXT("Init COM failed, can not connect server")); return FALSE; } BOOL bReturn = FALSE; do { // 连接服务器 HRESULT hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&m_pLoc); if (FAILED(hres)) { SetErrorCode(hres); SetErrorInfo(TEXT("Failed to create IWbemLocator object. Error code = 0x%x"), hres); break; } hres = m_pLoc->ConnectServer(_bstr_t(CStringW(CString(szServer))), NULL, NULL, 0, NULL, 0, 0, &m_pSvc); if (FAILED(hres)) { SetErrorCode(hres); SetErrorInfo(TEXT("Could not connect to server [%s]. Error code = 0x%x"), szServer, hres); break; } hres = CoSetProxyBlanket(m_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)) { SetErrorCode(hres); SetErrorInfo(TEXT("Could not set proxy blanket. Error code = 0x%x"), hres); break; } bReturn = TRUE; } while (FALSE); return bReturn;} BOOL CWMIUtil::ExecQuery(const TCHAR *szQuerySql){ // 有效性判断 if ((NULL == m_pLoc) || (NULL == m_pSvc)) { SetErrorCode(1); SetErrorInfo(TEXT("Do not connent to any server yet, can not exec query")); return FALSE; } if (CString(szQuerySql).IsEmpty()) { SetErrorCode(1); SetErrorInfo(TEXT("QuerySql is empty, can not exec")); return FALSE; } BOOL bReturn = FALSE; do { // 执行WMI查询语句 HRESULT hres = m_pSvc->ExecQuery(_bstr_t(L"WQL"), _bstr_t(CStringW(CString(szQuerySql))), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY , NULL, &m_pEnumerator); if (FAILED(hres)) { SetErrorCode(hres); SetErrorInfo(TEXT("ExecQuery [%s] failed. Error code = 0x%x"), szQuerySql, hres); break; } bReturn = TRUE; } while (FALSE); return bReturn;} BOOL CWMIUtil::Next(){ // 有效性判断 if (NULL == m_pEnumerator) { SetErrorCode(1); SetErrorInfo(TEXT("Do not exec any query yet, can not call next")); return FALSE; } BOOL bReturn = FALSE; do { // 枚举下一个类对象 ULONG uReturn = 0; HRESULT hres = m_pEnumerator->Next(WBEM_INFINITE, 1, &m_pCurObj, &uReturn); if (FAILED(hres)) { SetErrorCode(hres); SetErrorInfo(TEXT("Enumerate next object failed. Error code = 0x%x"), hres); break; } bReturn = uReturn; } while (FALSE); return bReturn;} BOOL CWMIUtil::GetProperty( const TCHAR *szValueName, TCHAR *szValue, const DWORD dwSizeInByte ){ // 有效性判断 if (NULL == m_pCurObj) { SetErrorCode(1); SetErrorInfo(TEXT("No object, so no property")); return FALSE; } if (CString(szValueName).IsEmpty() || (NULL == szValue) || dwSizeInByte <= 0) { SetErrorCode(1); SetErrorInfo(TEXT("Params invalid: value name is empty or value buffer is null")); return FALSE; } BOOL bReturn = FALSE; do { // 获取当前类对象的指定属性 VARIANT vtPropPath; HRESULT hres = m_pCurObj->Get(CStringW(CString(szValueName)), 0, &vtPropPath, 0, 0); if (FAILED(hres)) { SetErrorCode(hres); SetErrorInfo(TEXT("Get proterty [%s] value failed. Error code = 0x%x"), szValueName, hres); break; } CString csValue; switch(vtPropPath.vt) { case VT_BSTR: csValue = CString(CStringW(vtPropPath.bstrVal)); break; default: break; } VariantClear(&vtPropPath); if (!csValue.IsEmpty()) { memcpy_s(szValue, dwSizeInByte, csValue.GetString(), csValue.GetLength() * sizeof(TCHAR)); bReturn = TRUE; } } while (FALSE); return bReturn;}
注意:其中函数GetProperty只处理了vtPropPath.vt是VT_BSTR的情况。
下面来个使用示例。
我上一篇文章正好讲了获取进程路径的问题,那么就写一个获取进程路径的函数,其中dwPID是进程PID(输入参数),szFullPath是获取到的进程路径(输出参数):
BOOL GetProcessFullNameByPID( const DWORD dwPID, TCHAR *szFullPath, const DWORD dwSizeInByte ){ // 有效性判断 if (0 == dwPID || NULL == szFullPath || dwSizeInByte < sizeof(TCHAR)) { return FALSE; } BOOL bReturn = FALSE; do { // 先用GetModuleFileNameEx获取 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPID); if (NULL != hProcess) { if (GetModuleFileNameEx(hProcess, NULL, szFullPath, dwSizeInByte / sizeof(TCHAR))) { if (!CString(szFullPath).IsEmpty()) { bReturn = TRUE; } } else { const DWORD dwErrorCode = GetLastError(); if (299 != dwErrorCode) { ErrorLog(TEXT("GetModuleFileNameEx [PID = %lu] fail, error code is [%lu]\r\n"), dwPID, dwErrorCode); } else { // 299错误,是因为32位进程尝试获取64位进程的路径而导致的,这正是下面继续用WMI的理由,因此不处理这个错误 } } CloseHandle(hProcess); } else { ErrorLog(TEXT("OpenProcess [PID = %lu] fail, error code is [%lu]\r\n"), dwPID, GetLastError()); } // 若失败,再用WMI获取 if (bReturn) { break; } CWMIUtil wmi; if (!wmi.Init()) { ErrorLog(TEXT("wmi init fail, error code is [%lu], error msg is [%s]\r\n"), wmi.GetErrorCode(), wmi.GetErrorInfo()); break; } if (!wmi.ConnectServer()) { ErrorLog(TEXT("wmi connect server fail, error code is [%lu], error msg is [%s]\r\n"), wmi.GetErrorCode(), wmi.GetErrorInfo()); break; } CString csQuery; csQuery.Format(TEXT("SELECT * FROM Win32_Process WHERE ProcessId=\"%lu\""), dwPID); if (!wmi.ExecQuery(csQuery)) { ErrorLog(TEXT("wmi exec query fail, error code is [%lu], error msg is [%s]\r\n"), wmi.GetErrorCode(), wmi.GetErrorInfo()); break; } if (!wmi.Next()) { ErrorLog(TEXT("wmi next fail, error code is [%lu], error msg is [%s]\r\n"), wmi.GetErrorCode(), wmi.GetErrorInfo()); break; } if (!wmi.GetProperty(TEXT("ExecutablePath"), szFullPath, dwSizeInByte)) { ErrorLog(TEXT("wmi get property fail, error code is [%lu], error msg is [%s]\r\n"), wmi.GetErrorCode(), wmi.GetErrorInfo()); break; } bReturn = TRUE; } while (FALSE); return bReturn;}