封裝WMI查詢的簡單類CWMIUtilhtml
頭文件WMIUtil.h服務器
#pragma once #include <Wbemidl.h> class 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 <comdef.h> # 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的狀況。less
下面來個使用示例。函數
我上一篇文章正好講了獲取進程路徑的問題,那麼就寫一個獲取進程路徑的函數,其中dwPID是進程PID(輸入參數),szFullPath是獲取到的進程路徑(輸出參數):ui
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; }