WMI обнаруживает событие создания процесса - c ++ - PullRequest
0 голосов
/ 02 ноября 2018

Я пытаюсь создать программу событий уведомлений, когда открывается какой-то конкретный процесс. Я подписан на этот пост , и он работает. Я могу получить событие, когда notepad.exe или процесс PowerPoint открыт. Однако программа выполняется один раз, после того, как первый блокнот открыт, программа перестает проверять новый процесс блокнота. Я знаю, что мне может понадобиться цикл, но куда мне добавить цикл? Другой вопрос заключается в том, что я проверяю два типа процессов (блокнот и powerpoint), поэтому независимо от того, какой процесс открыт, событие будет инициировано. Можно ли узнать, какой процесс вызывает функцию? (Предположим, я открываю блокнот и могу узнать событие запуска процесса блокнота, а не powerpoint)

main.cpp

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

#pragma comment(lib, "wbemuuid.lib")
#include "CreationEvent.h"

class EventSink : public IWbemObjectSink {
    friend void CreationEvent::registerCreationCallback(TNotificationFunc callback);

    CComPtr<IWbemServices> pSvc;
    CComPtr<IWbemObjectSink> pStubSink;
    LONG m_IRef;
    CreationEvent::TNotificationFunc m_callback;

public:
    EventSink(CreationEvent::TNotificationFunc callback) :m_IRef(0), m_callback(callback){}
    ~EventSink(){
    }

    virtual ULONG STDMETHODCALLTYPE AddRef() {
        return InterlockedIncrement(&m_IRef);
    }

    virtual ULONG STDMETHODCALLTYPE Release() {
        LONG IRef = InterlockedDecrement(&m_IRef);
        if (IRef == 0)
            delete this;
        return IRef;
    }

    virtual HRESULT STDMETHODCALLTYPE 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;
    }

    virtual HRESULT STDMETHODCALLTYPE Indicate(
        LONG lObjectCount,
        IWbemClassObject __RPC_FAR *__RPC_FAR *apObjArray
    ){
        m_callback();
        /* Unregister event sink */
        pSvc->CancelAsyncCall(pStubSink);
        return WBEM_S_NO_ERROR;
    }
    virtual HRESULT STDMETHODCALLTYPE SetStatus(LONG IFlags, HRESULT hResult, BSTR strParam, IWbemClassObject __RPC_FAR *pObjParam) {
        return WBEM_S_NO_ERROR;
    }
};

void CreationEvent::registerCreationCallback(TNotificationFunc callback) {
    CComPtr<IWbemLocator> pLoc;
    CoInitializeEx(0, COINIT_MULTITHREADED);
    HRESULT 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;
        throw std::exception("CreationEvent initialization failed");
    }
    CComPtr<EventSink> pSink(new EventSink(callback));

    hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSink->pSvc);
    if (FAILED(hres)) {
        cout << "Could not connect. Error code = 0x" << hex << hres << endl;
        throw std::exception("CreationEvent initialization failed");
    }
    hres = CoSetProxyBlanket(pSink->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)) {
        cout << "Coult not set proxy blanket, Error code =0x" << hex << hres << endl;
        throw std::exception("CreationEvent initialization failed");
    }

    CComPtr<IUnsecuredApartment> pUnsecApp;
    hres = CoCreateInstance(CLSID_UnsecuredApartment, NULL, CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, (void**)&pUnsecApp);
    CComPtr<IUnknown> pStubUnk;
    pUnsecApp->CreateObjectStub(pSink, &pStubUnk);
    pStubUnk->QueryInterface(IID_IWbemObjectSink, (void**)&pSink->pStubSink);


    char buffer[512];
    sprintf_s(buffer, "SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process' AND (TargetInstance.Name = 'Notepad.exe' OR TargetInstance.Name = 'Powerpnt.exe')");

    hres = pSink->pSvc->ExecNotificationQueryAsync(_bstr_t("WQL"), _bstr_t(buffer), WBEM_FLAG_SEND_STATUS, NULL, pSink->pStubSink);

    if (FAILED(hres)) {
        cout << "ExecNotificationQueryAsync failed with = 0x" << hex << hres << endl;
        throw std::exception("CreationEvent initialization failed");
    }
}

void k() { cout << "process open" << endl; }

int main() {
    CreationEvent::registerCreationCallback(k);
    CoUninitialize();
} 

header.h

#pragma once
#ifndef _Header_h__
#define _Header_h__
#include <boost/function.hpp>
namespace CreationEvent {
    typedef boost::function<void(void)> TNotificationFunc;
    void registerCreationCallback(TNotificationFunc callback);
}
#endif

1 Ответ

0 голосов
/ 02 ноября 2018

Вы должны добавить цикл после вызова ExecNotificationQueryAsyncat в конце функции registerCreationCallback, это может быть вечный цикл с условием done или вы можете использовать WaitForSingleObject, затем создать событие и сигнализировать, когда хотите завершить процесс , также вы должны освободить все выделенные ресурсы.

Чтобы получить имя запущенного процесса, перейдите в функцию «Указать» и измените это

virtual HRESULT STDMETHODCALLTYPE Indicate(
        LONG lObjectCount,
        IWbemClassObject __RPC_FAR *__RPC_FAR *apObjArray
    ){
        for (int i = 0; i < lObjectCount; i++){
            _variant_t vtProp;
            _variant_t cn;

            hr = apObjArray[i]->Get(_bstr_t(L"TargetInstance"), 0, &vtProp, 0, 0)
            IUnknown* str = vtProp;
            HRESULT hr = str->QueryInterface(IID_IWbemClassObject, reinterpret_cast<void**>(&apObjArray[i]));
            if (SUCCEEDED(hr))
            {
                _variant_t cn;
                hr = apObjArray[i]->Get(L"Name", 0, &cn, NULL, NULL);
                //here is the name of the process
                //cn.bstrVal
                m_callback();
            }
        }

        /* Unregister event sink */
        //you should not unregister the event if you want to receive more notifications, do this after 
        //your forever loop in registerCreationCallback
        //pSvc->CancelAsyncCall(pStubSink);
        return WBEM_S_NO_ERROR;
    }

тогда вы можете отправить имя в качестве параметра к вашему обратному вызову

...