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

封装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
        {
            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;
}

https://blog.csdn.net/mkdym/article/details/8760975

posted @ 2019-04-26 16:34  乘于时  阅读(1613)  评论(0编辑  收藏  举报