您的位置:首页 > 编程语言 > C语言/C++

使用C++进行WMI查询的简单封装

2013-04-05 12:33 441 查看
封装WMI查询的简单类CWMIUtil

头文件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的情况。

下面来个使用示例。

我上一篇文章正好讲了获取进程路径的问题,那么就写一个获取进程路径的函数,其中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
{
ErrorL
4000
og(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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  WMI