簡體   English   中英

C/C++中如何跟蹤程序進程的完成情況

[英]How to track the completion of the program process in C/C++

我需要編寫一個程序,在程序過程完成后會做一些事情,比如計算器。 也就是說,我用計算器工作,然后我把它關掉,分別,它的過程完成,我的程序做我設置的動作。 我該怎么做呢? 如何跟蹤流程完成情況? 我google了一下,發現提示需要通過CreateProcess函數創建一個單獨的進程,然后使用WaitForSingleObject或者GetExitCodeProcess,但這不是我需要的,因為我不需要創建一個已經在運行的進程,或者我不太明白它是如何工作的。

您可以使用WMI to Monitor進程實例。 以下是如何通過 WMI 接收事件通知的完整步驟。

這里有一段跟蹤記事本操作的代碼片段,你可以參考:

#define CREATE 1
#define DELETE 0

using namespace std;

typedef function<void(void)> TNotificationFunc;
IWbemObjectSink* RegisterProcessCallback(IWbemServices* pSvc, TNotificationFunc callback, LPCWSTR ProcessName, BOOL flag);


class EventSink : public IWbemObjectSink {

    friend IWbemObjectSink* RegisterProcessCallback(IWbemServices* pSvc, TNotificationFunc callback, LPCWSTR ProcessName, BOOL flag);
    CComPtr<IWbemServices> pSvc;
    CComPtr<IWbemObjectSink> pStubSink;
    LONG m_IRef;
    TNotificationFunc m_callback;

public:
    EventSink(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
    ) {
        for (int i = 0; i < lObjectCount; i++)
        {
            m_callback();
            _variant_t vtProp;
            HRESULT hr = S_OK;
            hr = apObjArray[i]->Get(_bstr_t(L"TargetInstance"), 0, &vtProp, 0, 0);
            if (!FAILED(hr))
            {
                IUnknown* str = vtProp;
                hr = str->QueryInterface(IID_IWbemClassObject, reinterpret_cast<void**>(&apObjArray[i]));
                if (SUCCEEDED(hr))
                {
                    _variant_t cn;
                    hr = apObjArray[i]->Get(L"Handle", 0, &cn, NULL, NULL);
                    if (SUCCEEDED(hr))
                    {
                        if ((cn.vt == VT_NULL) || (cn.vt == VT_EMPTY))
                            wcout << "ProcessId : " << ((cn.vt == VT_NULL) ? "NULL" : "EMPTY") << endl;
                        else
                            wcout << "ProcessId : " << cn.bstrVal << endl;
                    }
                    VariantClear(&cn);
                }
            }
            VariantClear(&vtProp);
        }
        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 connect2WMI(IWbemServices** pSvc)
{
    HRESULT hres;
    CComPtr<IWbemLocator> pLoc;

    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");
    }
    hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, pSvc);
    if (FAILED(hres)) {
        cout << "Could not connect. Error code = 0x" << hex << hres << endl;
        throw std::exception("CreationEvent initialization failed");
    }
    hres = CoSetProxyBlanket(*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");
    }
}
IWbemObjectSink* RegisterProcessCallback(IWbemServices* pSvc, TNotificationFunc callback, LPCWSTR ProcessName, BOOL flag) {
    HRESULT hres;
    CComPtr<EventSink> pSink(new EventSink(callback));
    CComPtr<IUnsecuredApartment> pUnsecApp;
    hres = CoCreateInstance(CLSID_UnsecuredApartment, NULL, CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, (void**)&pUnsecApp);
    CComPtr<IUnknown> pStubUnk;
    pUnsecApp->CreateObjectStub(pSink, &pStubUnk);
    IWbemObjectSink* pStubSink = NULL;
    pStubUnk->QueryInterface(IID_IWbemObjectSink, (void**)&pStubSink);


    wstring buffer = L"SELECT * FROM ";
    if (flag == CREATE)
        buffer += L"__InstanceCreationEvent";
    else if (flag == DELETE)
        buffer += L"__InstanceDeletionEvent";
    buffer = buffer + L" WITHIN 1 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name = '" + ProcessName + L"'";
    hres = pSvc->ExecNotificationQueryAsync(_bstr_t(L"WQL"), _bstr_t(buffer.c_str()), WBEM_FLAG_SEND_STATUS, NULL, pStubSink);

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

void CreateEventCallBack() { cout << "Create " << endl; /*connect()*/ }
void DeleteEventCallBack() { cout << "Delete " << endl; /*disconnect()*/ }

int main() {
    CoInitializeEx(0, COINIT_MULTITHREADED);
    IWbemServices* pSvc = NULL;
    connect2WMI(&pSvc);
    IWbemObjectSink* CreateSink = RegisterProcessCallback(pSvc, CreateEventCallBack, L"notepad.exe", CREATE);
    IWbemObjectSink* DeleleSink = RegisterProcessCallback(pSvc, DeleteEventCallBack, L"notepad.exe", DELETE);

    getchar();
    cout << "Exit " << endl;
    pSvc->CancelAsyncCall(CreateSink);
    pSvc->CancelAsyncCall(DeleleSink);
    CreateSink->Release();
    DeleleSink->Release();
    pSvc->Release();
    CoUninitialize();
}

它非常適合我:

在此處輸入圖片說明

這個方法好像不太聰明,反正你用CreateProcess創建進程,然后得到進程id和進程名。 接下來,您監視所有進程列表並捕捉 id 消失的時刻。

DWORD hRetHandle = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot)
{
    PROCESSENTRY32W pe = { 0 };
    pe.dwSize = sizeof(PROCESSENTRY32W);
    if (Process32FirstW(hSnapshot, &pe))
    {
        do {
            if (wcsstr(pe.szExeFile, pswProcName))
            {
                hRetHandle = pe.th32ProcessID;
                break;
            }
        }while(Process32NextW(hSnapshot, &pe));
    }
    CloseHandle(hSnapshot);
}
return hRetHandle;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM