如何在c ++中检测win32进程创建/终止

Nun*_*uno 33 c++ winapi process

我知道要接收有关Win32进程创建或终止的通知,我们可以使用API​​实现NT内核模式驱动程序,该驱动程序PsSetCreateProcessNotifyRoutine()能够注册系统范围的回调函数,每当新进程启动,退出或者被终止.

这是否可以在不创建NT内核模式驱动程序的情况下,仅使用使用c ++的Win32 API函数?当然,不使用无限循环的基本解决方案查询活动进程列表.

是否有任何库或win32 API提供相同的功能(系统范围的回调,异步事件)?

Ant*_*n K 25

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);
Run Code Online (Sandbox Code Playgroud)

WaitOrTimerCallback一旦进程终止,此代码将调用.

  • 您确定严格要求使用“ PROCESS_ALL_ACCESS”吗?SYNCHRONIZE是否足够? (3认同)
  • 不要忘记调用[`UnregisterWait`函数](https://docs.microsoft.com/zh-cn/windows/desktop/api/winbase/nf-winbase-unregisterwait) (2认同)

And*_*ers 11

我唯一能想到的是WMI,不确定它是否提供了进程创建回调,但它可能值得研究.

  • 是的WMI可以提供我正在寻找的(进程创建/终止回调).如果有人有兴趣,那么请看看http://msdn.microsoft.com/en-us/library/aa390425%28VS.85%29.aspx谢谢 (11认同)

Nec*_*lis 6

您可以使用带有CBTProc的SetWindowsHookEx监视所有Window创建进程,但是除此之外的任何东西都需要WMI,Windows驱动程序或一点点' Black Magic '

  • 您已成为会员超过 7 年。你应该知道规则。指向场外资源的链接应被视为*可选*信息。如果您的答案本身不包含足够的信息,您不妨完全省略链接。到站外资源的链接确实无法访问,这意味着您的答案不再是。 (3认同)
  • 这只跟踪带有窗口的进程,但这对于很多场景来说都是一个很好的答案。这还将程序集注入到所述过程中。 (2认同)
  • CBT 挂钩无法跟踪进程创建/终止。这不是问题的答案。 (2认同)
  • 不会。CBT 挂钩可以监视窗口的创建和销毁。窗口创建/销毁与进程创建/终止之间没有关系。问题是问后者。 (2认同)

Rob*_*ert 6

Anders是正确的,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__
Run Code Online (Sandbox Code Playgroud)

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这里省略了初始化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
Run Code Online (Sandbox Code Playgroud)