WMI检测进程创建事件-c++

WMI detect process creation event - c++

本文关键字:事件 -c++ 创建 进程 检测 WMI      更新时间:2023-10-16

当某个特定进程打开时,我正在尝试创建一个通知事件程序。我关注这个帖子,它很有效。当notepad.exe或powerpoint进程打开时,我可以获取事件。

然而,程序只执行一次,在第一个记事本打开后,程序停止检查新的记事本进程。

我知道我可能需要一个循环,但我应该在哪里添加循环?

另一个问题是,我检查了两种类型的进程(记事本和powerpoint(,所以无论打开哪个进程,事件都会被触发。是否可以知道是哪个进程触发了该函数?

Suppose I open notepad, and I can know notepad process trigger event, not 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();
} 

页眉.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

您应该在函数registerCreationCallback末尾的ExecNotificationQueryAsync调用后添加一个循环,它可以是一个具有完成条件的永久循环,也可以使用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;
}

然后你可以将de name作为参数发送到你的回调