如何在c ++中检测win32进程的创build/终止
我知道要接收有关win32进程创build或终止的通知,我们可以使用API PsSetCreateProcessNotifyRoutine()来实现一个NT内核模式驱动程序,它提供了注册系统范围的callback函数的能力,每当新进程启动退出或终止。
我的问题是,如果这是可能的而不创build一个NT内核模式驱动程序,只使用win32 api函数使用c + +? 没有使用无限循环的基本解决scheme查询活动进程的列表当然。
是否有任何库或win32 API提供相同的function(系统范围的callback,asynchronous事件,…)?
谢谢
我能想到的唯一的事情就是WMI,不知道它是否提供了一个进程创buildcallback,但是可能值得研究。
WMI很棒,它也可以和进程名称一起工作。 尽pipe如果你需要跟踪进程终止,更轻量级和更简单的方法如下:
VOID CALLBACK WaitOrTimerCallback( _In_ PVOID lpParameter, _In_ BOOLEAN TimerOrWaitFired ) { MessageBox(0, L"The process has exited.", L"INFO", MB_OK); return; } DWORD dwProcessID = 1234; HANDLE hProcHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID); HANDLE hNewHandle; RegisterWaitForSingleObject(&hNewHandle, hProcHandle , WaitOrTimerCallback, NULL, INFINITE, WT_EXECUTEONLYONCE);
一旦进程终止,此代码将调用WaitOrTimerCallback
。
你可以使用SetWindowsHookEx和CBTProc监视所有的Window创build进程,但是不止如此,需要WMI,一个Windows驱动程序或者一点点的“ 黑魔法 ”
安德斯是正确的,WMI很好地为此工作。 由于我需要这个项目,我可以共享代码来检测(任意)进程终止(给定其ID):
ProcessTerminationNotification.h:
#ifndef __ProcessTerminationNotification_h__ #define __ProcessTerminationNotification_h__ #include <boost/function.hpp> namespace ProcessTerminationNotification { typedef boost::function< void(void) > TNotificationFunction; void registerTerminationCallback(TNotificationFunction callback, unsigned processId); } #endif // __ProcessTerminationNotification_h__
ProcessTerminationNotification.cpp:
#define _WIN32_DCOM #include <iostream> using namespace std; #include <comdef.h> #include <Wbemidl.h> #include <atlcomcli.h> #pragma comment(lib, "wbemuuid.lib") #include "ProcessTerminationNotification.h" class EventSink : public IWbemObjectSink { friend void ProcessTerminationNotification::registerTerminationCallback(TNotificationFunction callback, unsigned processId); CComPtr<IWbemServices> pSvc; CComPtr<IWbemObjectSink> pStubSink; LONG m_lRef; ProcessTerminationNotification::TNotificationFunction m_callback; public: EventSink(ProcessTerminationNotification::TNotificationFunction callback) : m_lRef(0) , m_callback(callback) {} ~EventSink() {} virtual ULONG STDMETHODCALLTYPE AddRef() { return InterlockedIncrement(&m_lRef); } virtual ULONG STDMETHODCALLTYPE Release() { LONG lRef = InterlockedDecrement(&m_lRef); if (lRef == 0) delete this; return lRef; } 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 since process is terminated */ pSvc->CancelAsyncCall(pStubSink); return WBEM_S_NO_ERROR; } virtual HRESULT STDMETHODCALLTYPE SetStatus( /* [in] */ LONG lFlags, /* [in] */ HRESULT hResult, /* [in] */ BSTR strParam, /* [in] */ IWbemClassObject __RPC_FAR *pObjParam ) { return WBEM_S_NO_ERROR; } }; void ProcessTerminationNotification::registerTerminationCallback( TNotificationFunction callback, unsigned processId ) { CComPtr<IWbemLocator> pLoc; 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("ProcessTerminationNotificaiton initialization failed"); } // Step 4: --------------------------------------------------- // Connect to WMI through the IWbemLocator::ConnectServer method CComPtr<EventSink> pSink(new EventSink(callback)); // 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, &pSink->pSvc ); if (FAILED(hres)) { cout << "Could not connect. Error code = 0x" << hex << hres << endl; throw std::exception("ProcessTerminationNotificaiton initialization failed"); } // Step 5: -------------------------------------------------- // Set security levels on the proxy ------------------------- hres = CoSetProxyBlanket( pSink->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; throw std::exception("ProcessTerminationNotificaiton initialization failed"); } // Step 6: ------------------------------------------------- // Receive event notifications ----------------------------- // Use an unsecured apartment for security 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); // The ExecNotificationQueryAsync method will call // The EventQuery::Indicate method when an event occurs char buffer[512]; sprintf_s(buffer, "SELECT * " "FROM __InstanceDeletionEvent WITHIN 1 " "WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.ProcessId=%u", processId); hres = pSink->pSvc->ExecNotificationQueryAsync( _bstr_t("WQL"), _bstr_t(buffer), WBEM_FLAG_SEND_STATUS, NULL, pSink->pStubSink); // Check for errors. if (FAILED(hres)) { cout << "ExecNotificationQueryAsync failed " "with = 0x" << hex << hres << endl; throw std::exception("ProcessTerminationNotificaiton initialization failed"); } }
请注意,初始化COM和COM进程安全性(CoInitializeEx和CoInitializeSecurity)的代码在这里省略,因为它应该在应用程序初始化中完成。
将其与全局函数一起使用,或使用boost :: bind连接到任意方法,例如后者:
class MyClass { public: void myProcessTerminationCallback() { cout << "Wohoo!!" << endl; } }; ProcessTerminationNotification::registerTerminationCallback( boost::bind(&MyClass::myProcessTerminationCallback, <pointer to MyClass instance>), 1234); // Process ID = 1234
正如之前的评论所暗示的那样,使用WMI来监视进程事件有一个缺点,因为WMI不能同步提供事件。
本书“Windows Internals Part 1”是指称为“Windows事件跟踪(ETW)”的机制,它是操作系统事件的低层机制。
以下博客文章展示了如何在.Net中使用ETW来监控进程: http : //blogs.msdn.com/b/vancem/archive/2013/03/09/using-traceevent-to-mine-information-in -os注册-ETW-providers.aspx
您可以通过挂钩CreateProcessInternalW
函数来监视进程创build。 通过挂钩这个函数,你甚至可以将DLL注入到新的进程中。
除WMI之外,或者如果您需要防止启动进程或线程,或者需要同步通知,则可以使用内核模式驱动程序方法。 例如,我们的CallbackProcess产品就是这样做的。
API挂钩应该是正确的方式来满足这样的事情。 你可以挂钩createProcess(A / W / asUserA / W ….等)和NtTerminateProcess