Using WMI

Hi all am using WMI in my application.
i am using the following Example.

http://msdn.microsoft.com/en-us/library/aa390425(v=vs.85).aspx

i have changed sleep(10000) to sleep(-1). so it runs forever not for a specific time.

I want process name as well which was created.?

How can i achieve it.What WQL i should use/or What changes i should make?

Thank you.
Last edited on
The modification you want to make will be in the third bit, the implementation of their custom 'EventSink' class. When a new instance of a class, in this case Win32_Process, is created this code uses the "IWbemServices::ExecNotificationQueryAsync()" function to callback to the "IWbemObjectSink::Indicate()" function*. The second parameter of "IWbemObjectSink::Indicate()" is an array of "IWbemObject" types and the first parameter is the number of elements in that array. So under the implementation of the "EventSink::Indicate()" function you'll want to add a VARIANT struct and a call to the "IWbemObject::Get()" method for each element in the array. The query would look something like this (NOT TESTED!)
apObjArray[i]->Get(L"Name"), 0, &Your_Variant, NULL, NULL);
The value you're looking for will be stored in Your_Variant.bstrVal; which is a wide string, so use 'std::wcout'. Let us know if you run into any more trouble, and for future reference, you may get help faster by posting this in the Windows section.



*: Notice that their class inherits from "IWbemObjectSink" as seen in their declaration of the class, so this is a polymorphic call. You don't often see this type of thing on MSDN outside of the COM and COM+ sections because they cater mostly toward supporting C.
Many - 2 thanks for reply.

When i made changes as you told as
1
2
3
VARIANT varName;
       		hres = apObjArray[i]->Get((L"Name"), 0, &varName, NULL, NULL);
		wcout << "Process Name : " << varName.bstrVal << endl;

but i got an error
Unhandled exception at 0x722147af (msvcr100d.dll) in ProcessUtility3.exe: 0xC0000005: Access violation reading location 0x00001001.

can you tell what is the problem?
Last edited on
It's not immediately obvious. It's possible that one of the processes that it caught died before you could read it's name? Could you post your full code?
Hi.
Actually i need a message whenever a process closes.
here is my full code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// EventSink.h
#ifndef EVENTSINK_H
#define EVENTSINK_H

#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#include<QtCore>
#include<QtGui>
# pragma comment(lib, "wbemuuid.lib")

class EventSink : public IWbemObjectSink/*,public QWidget*/
{
	//Q_OBJECT
    LONG m_lRef;
    bool bDone;

public:
    EventSink() { m_lRef = 0; }
   ~EventSink() { bDone = true; }

    virtual ULONG STDMETHODCALLTYPE AddRef();
    virtual ULONG STDMETHODCALLTYPE Release();        
    virtual HRESULT 
        STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv);

    virtual HRESULT STDMETHODCALLTYPE Indicate( 
            LONG lObjectCount,
            IWbemClassObject __RPC_FAR *__RPC_FAR *apObjArray
            );
        
    virtual HRESULT STDMETHODCALLTYPE SetStatus( 
            /* [in] */ LONG lFlags,
            /* [in] */ HRESULT hResult,
            /* [in] */ BSTR strParam,
            /* [in] */ IWbemClassObject __RPC_FAR *pObjParam
            );
};

#endif    // end of EventSink.h 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//eventsink.cpp
#include "eventsink.h"
#include <qmessagebox.h>
ULONG EventSink::AddRef()
{
    return InterlockedIncrement(&m_lRef);
}

ULONG EventSink::Release()
{
    LONG lRef = InterlockedDecrement(&m_lRef);
    if(lRef == 0)
        delete this;
    return lRef;
}

HRESULT EventSink::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;
}


HRESULT EventSink::Indicate(long lObjectCount,
    IWbemClassObject **apObjArray)
{
 HRESULT hres = S_OK;
 qDebug()<<"lObjectCount"<<lObjectCount;
    for (int i = 0; i < lObjectCount; i++)
    {
        printf("Event occurred : Process was deleted\n");
		
		 
	VARIANT varName;
  
	hres = apObjArray[i]->Get((L"Name"), 0, &varName, NULL, NULL);
	wcout << "Process Name : " << varName.bstrVal << endl;
        if (FAILED(hres))
        {
            cout << "Failed to get the data from the query"
               << " Error code = 0x"
                << hex << hres << endl;
            return WBEM_E_FAILED;       // Program has failed.
        }

 }

    return WBEM_S_NO_ERROR;
}

HRESULT EventSink::SetStatus(
            /* [in] */ LONG lFlags,
            /* [in] */ HRESULT hResult,
            /* [in] */ BSTR strParam,
            /* [in] */ IWbemClassObject __RPC_FAR *pObjParam
        )
{
    if(lFlags == WBEM_STATUS_COMPLETE)
    {
        printf("Call complete. hResult = 0x%X\n", hResult);
    }
    else if(lFlags == WBEM_STATUS_PROGRESS)
    {
        printf("Call in progress.\n");
    }

    return WBEM_S_NO_ERROR;
}    // end of EventSink.cpp 
continue...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//main()
HRESULT hres;

    // Step 1: --------------------------------------------------
    // Initialize COM. ------------------------------------------

    hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. Error code = 0x" 
             << hex << hres << endl;

        return 1;                  // Program has failed.
    }

	// Step 2: --------------------------------------------------
    // Set general COM security levels --------------------------

    hres =  CoInitializeSecurity(
        NULL, 
        -1,                          // COM negotiates service
        NULL,                        // Authentication services
        NULL,                        // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
        NULL,                        // Authentication info
        EOAC_NONE,                   // Additional capabilities 
        NULL                         // Reserved
        );

                      
    if (FAILED(hres))
    {
        cout << "Failed to initialize security. Error code = 0x" 
             << hex << hres << endl;
        CoUninitialize();
        return 1;                      // Program has failed.
    }
    
	// Step 3: ---------------------------------------------------
    // Obtain the initial locator to WMI -------------------------

    IWbemLocator *pLoc = NULL;

    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;
        CoUninitialize();
        return 1;                 // Program has failed.
    }


	 // Step 4: ---------------------------------------------------
    // Connect to WMI through the IWbemLocator::ConnectServer method

    IWbemServices *pSvc = NULL;
 
    // 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, 
        &pSvc
    );
     
    if (FAILED(hres))
    {
        cout << "Could not connect. Error code = 0x" 
             << hex << hres << endl;
        pLoc->Release();     
        CoUninitialize();
        return 1;                // Program has failed.
    }

    cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;


    // Step 5: --------------------------------------------------
    // Set security levels on the proxy -------------------------

    hres = CoSetProxyBlanket(
        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;
        pSvc->Release();
        pLoc->Release();     
        CoUninitialize();
        return 1;               // Program has failed.
    }

    // Step 6: -------------------------------------------------
    // Receive event notifications -----------------------------

    // Use an unsecured apartment for security
    IUnsecuredApartment* pUnsecApp = NULL;

    hres = CoCreateInstance(CLSID_UnsecuredApartment, NULL, 
        CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, 
        (void**)&pUnsecApp);
 
    EventSink* pSink = new EventSink;
    pSink->AddRef();

    IUnknown* pStubUnk = NULL; 
    pUnsecApp->CreateObjectStub(pSink, &pStubUnk);

    IWbemObjectSink* pStubSink = NULL;
    pStubUnk->QueryInterface(IID_IWbemObjectSink,
        (void **) &pStubSink);

    // The ExecNotificationQueryAsync method will call
    // The EventQuery::Indicate method when an event occurs
	//Win32_Process obj;
    hres = pSvc->ExecNotificationQueryAsync  (
        _bstr_t("WQL"), 
        _bstr_t("SELECT *"
            "FROM __InstanceDeletionEvent WITHIN 1 
            "WHERE TargetInstance ISA 'Win32_Process'"),  
        WBEM_FLAG_SEND_STATUS, 
        NULL, 
        pStubSink);	

    // Check for errors.
    if (FAILED(hres))
    {
        printf("ExecNotificationQueryAsync failed "
            "with = 0x%X\n", hres);
        pSvc->Release();
        pLoc->Release();
        pUnsecApp->Release();
        pStubUnk->Release();
        pSink->Release();
        pStubSink->Release();
        CoUninitialize();    
        return 1;
    }

	//-------------------------------------------------------------------//
	

    // Wait for the event
    Sleep(-1);
         
    hres = pSvc->CancelAsyncCall(pStubSink);

    // Cleanup
    // ========

    pSvc->Release();
    pLoc->Release();
    pUnsecApp->Release();
    pStubUnk->Release();
    pSink->Release();
    pStubSink->Release();
    CoUninitialize();
 


i successfully printed outs the message whenever a process closes.
but i need process name as well which was closed.
thanks.
Last edited on
That might be a problem then because the instance of the 'IWbemObject' doesn't actually exist anymore. Is this a process that you wrote your self where you could just tack on a destructor on that tells you when it dies?
But..i can't understand why it not returning name of that process while querying.
i used "SELECT *"
"FROM __InstanceDeletionEvent WITHIN 1
"WHERE TargetInstance ISA 'Win32_Process'"
in my WML.
why?
Topic archived. No new replies allowed.