[英]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.