Search code examples
c++processwmiwmi-querywql

C++: Monitor process creation and termination in Windows


I happened to see the following portion of code here.

$Obj.ExecNotificationQueryAsync($hObj, "SELECT * FROM __InstanceCreationEvent WITHIN 0.5 WHERE TargetInstance ISA 'Win32_Process'")
$Obj.ExecNotificationQueryAsync($hObj, "SELECT * FROM __InstanceDeletionEvent WITHIN 0.5 WHERE TargetInstance ISA 'Win32_Process'")


Switch $OB.Path_.Class
            Case "__InstanceCreationEvent"
                ConsoleWrite("+~>" & _ProcessGetPath($OB.TargetInstance.ProcessID) & @CR)
            Case "__InstanceDeletionEvent"
                ConsoleWrite("!~>" & $OB.TargetInstance.ProcessID & @CR)
        EndSwitch

I used the same WQL queries to monitor processes in C++. Is there something similar in C++ by which I can know whether it was creation or termination of process. I tried using __CLASS, but it gives the output as Win32_Process. I am coding in MSVS2010.

Please help.Thankyou

EDIT 1: WQL QUERY ADDED

hres = pSvc->ExecNotificationQueryAsync(
        _bstr_t("WQL"), 
        _bstr_t("SELECT * " 
            "FROM __InstanceDeletionEvent WITHIN 1 "
            "WHERE TargetInstance ISA 'Win32_Process' "), 
        WBEM_FLAG_SEND_STATUS, 
        NULL, 
        pStubSink);


     hres = pSvc->ExecNotificationQueryAsync(
        _bstr_t("WQL"), 
        _bstr_t("SELECT * " 
            "FROM __InstanceCreationEvent WITHIN 1 "
            "WHERE TargetInstance ISA 'Win32_Process'"), 
        WBEM_FLAG_SEND_STATUS, 
        NULL, 
        pStubSink);

Using the above code, I get the name of the process, either created or terminated, printed into the console from the IWbemObjectSink::Indicate method.


Solution

  • In order to detect the creation and termination of a process using a single WQL sentence you can use the __InstanceOperationEvent class like so.

    Select * From __InstanceOperationEvent Within 1 Where TargetInstance ISA  Win32_Process
    

    Then if you want determine the type (class) of the event arrived you must eveluate the __Class property.

    Try this sample

    HRESULT EventSink::Indicate(long lObjectCount,
                                IWbemClassObject **apObjArray)
    {
        HRESULT hr = S_OK;
        _variant_t vtProp;
    
        for (int i = 0; i < lObjectCount; i++)
        {
            bool CreateorDel = false;
            _variant_t cn;
            hr = apObjArray[i]->Get(_bstr_t(L"__Class"), 0, &cn, 0, 0);
            if (SUCCEEDED(hr))
            {
                wstring LClassStr(cn.bstrVal);
                if (0 == LClassStr.compare(L"__InstanceDeletionEvent") )
                {
                    wcout << "Deletion" << endl;
                    CreateorDel = true;
                }
                else if (0 == LClassStr.compare(L"__InstanceCreationEvent"))
                {
                    wcout << "Creation" << endl;
                    CreateorDel = true;
                }
                else
                {
                    CreateorDel = false;
                    //wcout << "Modification " << endl;             
                }
            }
            VariantClear(&cn);  
    
            if (CreateorDel)
            {
                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"Name", 0, &cn, NULL, NULL );
                        if ( SUCCEEDED( hr ) )
                        {
    
                            if ((cn.vt==VT_NULL) || (cn.vt==VT_EMPTY))
                                wcout << "Name : " << ((cn.vt==VT_NULL) ? "NULL" : "EMPTY") << endl;
                            else
                                wcout << "Name : " << cn.bstrVal << endl;
                        }
                        VariantClear(&cn);              
    
                        hr = apObjArray[i]->Get( L"Handle", 0, &cn, NULL, NULL );
                        if ( SUCCEEDED( hr ) )
                        {
                            if ((cn.vt==VT_NULL) || (cn.vt==VT_EMPTY))
                                wcout << "Handle : " << ((cn.vt==VT_NULL) ? "NULL" : "EMPTY") << endl;
                            else
                                wcout << "Handle : " << cn.bstrVal << endl;
                        }
                        VariantClear(&cn);
                    }
                }
                VariantClear(&vtProp);
            }
    
        }
    
        return WBEM_S_NO_ERROR;
    }