• WMI 事件通知


    srcURL: http://msdn2.microsoft.com/en-us/library/aa390425(VS.85).aspx
                                                 
    下面的示例代码展示了 COM 初始化,连接到本机的 WMI ,接收事件,然后清理的过程. 当有新进程创建时,用户会得到通过.事件是异步接收。

    步骤 1-5 是初始设置和连接到WMI , 步骤6 是接收事件.
     

    过程:

    1. 调用 CoInitializeEx 初始化 COM.

    2. 调用 CoInitializeSecurity 初始化 COM 进程安全。
       window 2000 需要在 CoInitializeSecurity 的 pAuthList 参数中指定 SOLE_AUTHENTICATION_LIST 设置默认的安全认证.

    3. 通过调用 CoCreateInstance 来获得WMI定位器(locator) .


    4. 通过调用 IWbemLocator::ConnectServer 并指定参数 strNetworkResource 为 "root\cimv2", 这样我们可以获得指向 "IWbemServices" 的指针.

    5. 调用 CoSetProxyBlanket 设置 IWbemServices 的代理安全.这样 WMI 服务能够模拟客户端角色.

    6. 使用  IWbemServices::ExecNotificationQueryAsync 方法 来接收异步事件. 要接收异步事件,我们必须实现 IWbemObjectSink. 下面的代码在 EventSink 类里提供了实现.  在任何时候接收到事件时, IWbemServices::ExecNotificationQueryAsync 都会调用 EventSink::Indicate .  在该代码示例中,当有进程被创建时 EventSink::Indicate 就会被调用.
    运行下面的代码,打开 notepad.exe, 通知事件就会被触发.


    #include "eventsink.h"

    int main(int iArgCnt, char ** argv)
    {
        HRESULT hres;

        // Step 1: --------------------------------------------------
        // Initialize COM. ------------------------------------------

        hres =  CoInitializeEx(0, COINIT_MULTITHREADED);
        if (FAILED(hres))
        {
            cout << "Failed to initialize COM library. Error code = 0x"
                 << hex << hres << endl;
            return 1;                  // Program has failed.
        }

        // Step 2: --------------------------------------------------
        // Set general COM security levels --------------------------
        // Note: If you are using Windows 2000, you need to specify -
        // the default authentication credentials for a user by using
        // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
        // parameter of CoInitializeSecurity ------------------------

        hres =  CoInitializeSecurity(
            NULL,
            -1,                          // COM negotiates service
            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
            );

                         
        if (FAILED(hres))
        {
            cout << "Failed to initialize security. Error code = 0x"
                 << hex << hres << endl;
            CoUninitialize();
            return 1;                      // Program has failed.
        }
       
        // Step 3: ---------------------------------------------------
        // Obtain the initial locator to WMI -------------------------

        IWbemLocator *pLoc = NULL;

        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();
            return 1;                 // Program has failed.
        }

        // Step 4: ---------------------------------------------------
        // Connect to WMI through the IWbemLocator::ConnectServer method

        IWbemServices *pSvc = NULL;
     
        // Connect to the local root\cimv2 namespace
        // and obtain pointer pSvc to make IWbemServices calls.
        hres = pLoc->ConnectServer(
            _bstr_t(L"ROOT\\CIMV2"),
            NULL,
            NULL,
            0,
            NULL,
            0,
            0,
            &pSvc
        );
        
        if (FAILED(hres))
        {
            cout << "Could not connect. Error code = 0x"
                 << hex << hres << endl;
            pLoc->Release();    
            CoUninitialize();
            return 1;                // Program has failed.
        }

        cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;


        // 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();
            return 1;               // Program has failed.
        }

        // Step 6: -------------------------------------------------
        // Receive event notifications -----------------------------

        // Use an unsecured apartment for security
        IUnsecuredApartment* pUnsecApp = NULL;    // 这些指针的定义可以用 CComQIPtr或 CComPtr 自动管理对象的生存周期

        hres = CoCreateInstance(CLSID_UnsecuredApartment, NULL,
            CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment,
            (void**)&pUnsecApp);
     
        EventSink* pSink = new EventSink;
        pSink->AddRef();

        IUnknown* pStubUnk = NULL;
        pUnsecApp->CreateObjectStub(pSink, &pStubUnk);

        IWbemObjectSink* pStubSink = NULL;
        pStubUnk->QueryInterface(IID_IWbemObjectSink,
            (void **) &pStubSink);

        // The ExecNotificationQueryAsync method will call
        // The EventQuery::Indicate method when an event occurs
        hres = pSvc->ExecNotificationQueryAsync(
            _bstr_t("WQL"),
            _bstr_t("SELECT * "
                "FROM __InstanceCreationEvent WITHIN 1 "
                "WHERE TargetInstance ISA 'Win32_Process'"),
            WBEM_FLAG_SEND_STATUS,
            NULL,
            pStubSink);

        // Check for errors.
        if (FAILED(hres))
        {
            printf("ExecNotificationQueryAsync failed "
                "with = 0x%X\n", hres);
            pSvc->Release();
            pLoc->Release();
            pUnsecApp->Release();
            pStubUnk->Release();
            pSink->Release();
            pStubSink->Release();
            CoUninitialize();   
            return 1;
        }

        // Wait for the event
        Sleep(10000);
            
        hres = pSvc->CancelAsyncCall(pStubSink);

        // Cleanup
        // ========

        pSvc->Release();
        pLoc->Release();
        pUnsecApp->Release();
        pStubUnk->Release();
        pSink->Release();
        pStubSink->Release();
        CoUninitialize();

        return 0;   // Program successfully completed.
     
    }


    //----------------------------------     EventSink.h --------------------------------------------------//

    #ifndef EVENTSINK_H
    #define EVENTSINK_H

    #define _WIN32_DCOM
    #include <iostream>
    using namespace std;
    #include <comdef.h>
    #include <Wbemidl.h>

    # pragma comment(lib, "wbemuuid.lib")

    class EventSink : public IWbemObjectSink
    {
        LONG m_lRef;
        bool bDone;

    public:
        EventSink() { m_lRef = 0; }
       ~EventSink() { bDone = true; }

        virtual ULONG STDMETHODCALLTYPE AddRef();
        virtual ULONG STDMETHODCALLTYPE Release();       
        virtual HRESULT
            STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv);

        virtual HRESULT STDMETHODCALLTYPE Indicate(
                LONG lObjectCount,
                IWbemClassObject __RPC_FAR *__RPC_FAR *apObjArray
                );
           
        virtual HRESULT STDMETHODCALLTYPE SetStatus(
                /* [in] */ LONG lFlags,
                /* [in] */ HRESULT hResult,
                /* [in] */ BSTR strParam,
                /* [in] */ IWbemClassObject __RPC_FAR *pObjParam
                );
    };

    #endif


    // ------------------------------------------ EventSink.cpp ------------------------------------------------ //
    //
    #include "eventsink.h"

    ULONG EventSink::AddRef()
    {
        return InterlockedIncrement(&m_lRef);
    }

    ULONG EventSink::Release()
    {
        LONG lRef = InterlockedDecrement(&m_lRef);
        if(lRef == 0)
            delete this;
        return lRef;
    }

    HRESULT EventSink::QueryInterface(REFIID riid, void** ppv)
    {
        if (riid == IID_IUnknown || riid == IID_IWbemObjectSink)
        {
            *ppv = (IWbemObjectSink *) this;
            AddRef();
            return WBEM_S_NO_ERROR;
        }
        else return E_NOINTERFACE;
    }


    HRESULT EventSink::Indicate(long lObjectCount,
        IWbemClassObject **apObjArray)
    {
     HRESULT hres = S_OK;

        for (int i = 0; i < lObjectCount; i++)
        {
            printf("Event occurred\n");
        }

        return WBEM_S_NO_ERROR;
    }

    HRESULT EventSink::SetStatus(
                /* [in] */ LONG lFlags,
                /* [in] */ HRESULT hResult,
                /* [in] */ BSTR strParam,
                /* [in] */ IWbemClassObject __RPC_FAR *pObjParam
            )
    {
        if(lFlags == WBEM_STATUS_COMPLETE)
        {
            printf("Call complete. hResult = 0x%X\n", hResult);
        }
        else if(lFlags == WBEM_STATUS_PROGRESS)
        {
            printf("Call in progress.\n");
        }

        return WBEM_S_NO_ERROR;
    }    // end of EventSink.cpp


    }


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Blue_Dream_/archive/2007/12/21/1956939.aspx

  • 相关阅读:
    OpenCV---在图片上加入文字
    DosBox 报错 this program requires dosxnt.exe to be in your path
    iOS开发-UITableView单选多选/复选实现1
    LeetCode第七题,Reverse Integer
    【PostgreSQL】PostgreSQL操作-psql基本命令
    Bootstrap的js插件之弹出框(popover)
    Qt Quick 图像处理实例之美图秀秀(附源代码下载)
    【甘道夫】并行化频繁模式挖掘算法FP Growth及其在Mahout下的命令使用
    用Visual Studio高版本号打开低版本号的project,转换时出现错误:fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
    如何安装ArchLinux
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1796508.html
Copyright © 2020-2023  润新知