Win64Visual C++ 9.0STLVisual C++ 7.1Visual C++ 8.0Visual C++ 7.0Win32Visual Studio 2008设计 / 图形Visual C++ 6.0架构师高级初级C中级开发Visual StudioWindowsC++
使用 EnumProcess 进行进程创建通知
使用 EnumProcess 轮询以在用户模式下获取进程创建通知。

引言
Windows 在用户模式下没有提供基于事件的进程相关通知机制。因此,任何解决方案本质上都是基于轮询的。一种选择是使用 EnumProcess
API。也可以使用 WMI。我从未用过 WMI,所以无法说明使用基于 WMI 的方法的开销。但有一点是肯定的,使用 WMI 会带来对 WMI 服务的额外依赖。在本文中,我将考虑基于 EnumProcess
的方法。请参阅 此处 获取基于 WMI 的方法。
Using the Code
示例类 CProcessNotify
封装了 EnumProcess
轮询功能。在单独的线程中以用户提供的间隔进行轮询。通知在该线程中传递。但是,如果您需要调用线程阻塞,可以修改该类以适应您的目的。这是主要代码。基本上,使用 STL set_compare
比较从 EnumProcess
返回的进程 ID 列表。当前列表和先前列表的差异给出了创建和终止的 ID。当前方法有一个小缺点。如果一个进程消失,并且在轮询间隔内出现一个具有相同 ID 的新进程,它将无法识别。对此的解决方法是使用 GetProcessTimes
API 存储进程启动时间以及 ID。
typedef std::vector<dword> PIDLIST;
typedef std::vector<dword>::iterator PIDLISTITER;
const DWORD nSize = 1024;
PIDLIST vPidListPrev;
for (;;)
{
DWORD nRet = WaitForSingleObject(
m_hQuit,
m_nEnumInterval);
if (WAIT_TIMEOUT != nRet)
{
return nRet;
}
PIDLIST vPidListNext(nSize);
DWORD nNeeded = 0;
BOOL bRet = EnumProcesses(
&vPidListNext[0],
nSize*sizeof(DWORD),
&nNeeded);
if (!bRet)
{
return GetLastError();
}
vPidListNext.resize(nNeeded / sizeof(DWORD));
sort(
vPidListNext.begin(),
vPidListNext.end());
if (vPidListPrev.empty())
{
if (!m_bNotifyCurrent)
{
vPidListPrev = vPidListNext;
continue;
}
}
if (vPidListNext.size() == vPidListPrev.size())
{
int nRet = memcmp(
&vPidListNext[0],
&vPidListPrev[0],
nNeeded);
if (0 == nRet)
{
continue;
}
}
PIDLIST vPidListAdded(nSize);
PIDLISTITER itAdded = set_difference(
vPidListNext.begin(),
vPidListNext.end(),
vPidListPrev.begin(),
vPidListPrev.end(),
vPidListAdded.begin());
for (PIDLISTITER it1 = vPidListAdded.begin() ; it1 != itAdded ; it1++)
{
BOOL bRet = OnNotify(*it1, TRUE);
if (!bRet)
{
return ERROR_CANCELLED;
}
DWORD nRet = WaitForSingleObject(
m_hQuit,
0);
if (WAIT_TIMEOUT != nRet)
{
return nRet;
}
}
PIDLIST vPidListRemoved(nSize);
PIDLISTITER itRemoved = set_difference(
vPidListPrev.begin(),
vPidListPrev.end(),
vPidListNext.begin(),
vPidListNext.end(),
vPidListRemoved.begin());
for (PIDLISTITER it1 = vPidListRemoved.begin() ; it1 != itRemoved ; it1++)
{
BOOL bRet = OnNotify(*it1, FALSE);
if (!bRet)
{
return ERROR_CANCELLED;
}
DWORD nRet = WaitForSingleObject(
m_hQuit,
0);
if (WAIT_TIMEOUT != nRet)
{
return nRet;
}
}
vPidListPrev = vPidListNext;
}
欢迎提出评论。