Win32進程創建/終止我知道,收到有關Win32進程創建或終止,我們可能會使用提供了註冊全系統的回調函數的能力的API PsSetCreateProcessNotifyRoutine()
實現NT內核模式驅動程序通知其每當新進程啓動,退出或終止時由OS調用。如何檢測C++
這可能沒有創建一個NT內核模式驅動程序,只使用Win32 API函數使用c + +?不使用無限循環的基本解決方案查詢當然的活動進程列表。
是否有任何庫或win32 API提供相同的功能(系統範圍的回調,異步事件)?
Win32進程創建/終止我知道,收到有關Win32進程創建或終止,我們可能會使用提供了註冊全系統的回調函數的能力的API PsSetCreateProcessNotifyRoutine()
實現NT內核模式驅動程序通知其每當新進程啓動,退出或終止時由OS調用。如何檢測C++
這可能沒有創建一個NT內核模式驅動程序,只使用Win32 API函數使用c + +?不使用無限循環的基本解決方案查詢當然的活動進程列表。
是否有任何庫或win32 API提供相同的功能(系統範圍的回調,異步事件)?
我能想到的唯一的事情是WMI,不知道,如果它提供了一個進程創建回調,但它可能是值得研究的。
API掛鉤應該是正確的方式來滿足這樣的事情。您可以掛鉤的CreateProcess(A/W/asUserA/W ....等)和NtTerminateProcess
這不能實現系統範圍的監控除非你在內核和PatchGuard中執行,這是不可能的。 – 2017-09-27 12:38:11
您可以監控所有窗口使用SetWindowsHookEx與CBTProc創建進程,但是什麼比這更要求要麼WMI,Windows的驅動程序或一點點''
這隻跟蹤Windows的進程,但對於很多場景來說這是一個很好的答案。這也將組裝注入到所述過程中。 – 2015-08-27 21:07:12
CBT掛鉤無法跟蹤進程創建/終止。這不是對這個問題的回答。 – IInspectable 2017-06-09 15:19:16
@IInspectable:CBT鉤子可以跟蹤窗口進程;然而,我的答案的其餘部分回答了這個問題;就基於窗口的流程而言,CBT鉤子很簡單。 – Necrolis 2017-06-09 19:52:26
安德斯是正確的,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 ::綁定連接到後者的任意方法,例如:
class MyClass
{
public:
void myProcessTerminationCallback() { cout << "Wohoo!!" << endl; }
};
ProcessTerminationNotification::registerTerminationCallback(
boost::bind(&MyClass::myProcessTerminationCallback, <pointer to MyClass instance>),
1234); // Process ID = 1234
有沒有人知道WMI如何在內部實現事件? – 2014-02-20 18:01:39
根據「Windows Internals Part 1」一書,有一種名爲「Windows事件跟蹤(ETW)的機制」,它能夠跟蹤進程創建和終止。最終,WMI解決方案存在一個重大缺陷,因爲它不能實時(同步)提供事件。通過查看WMI WQL的WITHIN子句可以看出。 – 2014-02-20 21:49:28
實時需要信息的情況很少,如果有的話。在99.999%的案例中,足以知道該過程已經死亡。 – Robert 2014-02-21 10:11:05
您可以通過掛鉤CreateProcessInternalW
功能監視進程創建。通過掛鉤這個函數,你甚至可以將DLL注入到新進程中。
由於已經由以前的評論暗示,有使用WMI監視進程事件WMI未提供事件同步,.i.e一個缺點。耽擱很短。
書「Windows內部第1部分」指的是一個名爲「Windows事件跟蹤(ETW)」,這是操作系統事件的低級別機制機制。
下面的博客文章介紹如何ETW可以在淨用來監視進程: http://blogs.msdn.com/b/vancem/archive/2013/03/09/using-traceevent-to-mine-information-in-os-registered-etw-providers.aspx
不幸的是,事實證明,ETW並沒有提供同步/實時事件。 ETW事件也受到緩衝。 – 2014-02-22 18:58:08
WMI是偉大的,它與進程名工作過。但如果你需要跟蹤進程終止了更輕巧,更容易的方法是:
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
一旦終止該進程。
有沒有辦法使用您的解決方案檢測該進程的退出代碼? – 2014-10-31 23:26:10
有沒有像這樣的方法,但跟蹤過程創建? – brunoqc 2014-11-07 15:41:06
@brunoqc我在這個問題中發現了WMI的方式。 – 2014-11-07 19:09:16
除了WMI,或者如果您需要阻止進程或線程啓動,或者需要同步通知時,您可以使用內核模式驅動程序方法。例如,我們的CallbackProcess產品就是這樣做的。
是的WMI可以提供我正在尋找(進程創建/終止回調)。 如果有人對如何看看http://msdn.microsoft.com/en-us/library/aa390425%28VS.85%29.aspx 感興趣,謝謝 – Nuno 2010-08-24 16:30:49