需要源代码Email向我所取。
Windows的任务管理器,可以用来查看当前系统中运行的进程信息,这些信息包括进程的名称、ID、CPU占用率、占用CPU的时间以及占用内存的情况。有的时候,比如出于安全的考虑,可能希望了解关于某个进程的时间信息,比如进程创建的时间、进程已经运行了多长的时间、进程的内核模式占用时间和进程在用户模式的使用时间等。这时候,进程管理器就显得无能为力了。下面说说利用VC++编程实现获取系统中各进程时间信息的方法。实例完成后的运行效果如下图所示。
关键技术
首先介绍本实例将要用到的几个关键技术。
技术一、GetProcessTimes函数的使用
利用函数GetProcessTimes,能够获取指定进程的四种时间信息,将这些时间信息转换成可读的字符串后进行显示,就可以实现本实例的关键功能。下面的代码片段说明了使用GetProcessTimes的具体方法。
HANDLE hProcess;
FILETIME ftCreateing,
ftExit,
ftKernel,
ftUser;
GetProcessTimes(hProcess,&ftCreateing,&ftExit,&ftKernel,&ftUser);
技术二、计算运行时间
进程的运行时间实际上是一个时间段,即从该进程创建的时间到当前时间的间隔段。计算这个时间段原本比较麻烦,因为它带来了对时间对象进行时、分、秒的转换问题。幸运的是,COleDataTime类为程序设计带来了极大的方便。该类的一个应用代码片段如下:
ColeDataTime timeNow = ColeDataTime::GetCurrentTime();
TimeCreation = ftCreation;
ColeDataTimeSpan timeDiff = timeNow – timeCreation;
这样,开发人员就可以使用COleDataTimeSpan所提供的许多方法来获取时、分、秒等信息。
技术三、计算核心时间和用户时间。
进程在Windows操作系统下运行通常具有两种模式,一种是内核模式(Kernel:Level 0),另一种是用户模式(User:Level 3)。进程往往在这两种模式之间来回切换。实例开发遇到的问题是,获取该时间保存在FILETIME结构中是以千万分之一秒为单位进行计数的。这给程序进行信息的显示带来了困难。解决的方法有两个,分别介绍如下。
方法一、使用一些基本的算术将数据转换为秒单位。比如:
__int64 i64Kernel == *((__int64 *) &ftKernel);
DWORD dwKernel = (DWORD) (i64Kernel / 10000000U);
可以通过定义下面的联合体来方便编程:
union
{
FILETIME ftKernel;
__int64 i64Kernel;
}timeKernel;
timeKernel.ftKernel = ftKernel;
DWORD dwKernel = (DWORD) (timeKernel.i64Kernel / 10000000U );
方法二、使用FileTimeToSystemTime API函数。该函数将转换的结构保存到一个SYSTEMTIME结构中,其成员变量wHour,wMinute和wSecond即为转换后的数据信息。示例代码片段如下:
SYSTEMTIME stKernel;
FileTimeToSystemTime(&ftKernel , &stKernel);
用户模式时间的转换与上述方法相同。
关键实现代码
下面给出实例实现的关键代码。实例基于对话框创建,使用列表框进行信息的显示,代码中m_lcProcessInfo即为列表框控制对象。
用户列举进程时间信息的函数Process(),具体代码如下。
void CProcessTimeDlg::Process()
{
DWORD dwProcessIDs[150],dwSize,dwNeeded;
HANDLE hProcess;
HMODULE hModuleHandle;
FILETIME ftCreation,ftExit,ftKernel,ftUser;
SYSTEMTIME stKernel,stUser;
CString strName,strData;
int nIndex,nProcessCount,nItem;
COleDateTime timeCreation,timeNow;
COleDateTimeSpan timeDiff;
if (EnumProcesses(dwProcessIDs, sizeof(dwProcessIDs), &dwSize) == TRUE)
{
timeNow = COleDateTime::GetCurrentTime();
nProcessCount = dwSize / sizeof(DWORD);
for (nIndex = 0; nIndex < nProcessCount; nIndex++)
{
hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, dwProcessIDs[nIndex]);
if (NULL != hProcess)
{
strData.Format("%X", dwProcessIDs[nIndex]);
nItem = m_lcProcessInfo.InsertItem(nIndex, strData);
if (EnumProcessModules(hProcess, &hModuleHandle, sizeof(hModuleHandle), &dwNeeded) == TRUE)
{
if (GetModuleBaseNames(hProcess, hModuleHandle, strName) > 0)
{
m_lcProcessInfo.SetItemText(nItem, 1, strName);
if (GetProcessTimes(hProcess, &ftCreation, &ftExit, &ftKernel, &ftUser) == TRUE)
{
timeCreation = ftCreation;
strData.Format("%02d/%02d/%d - %02d:%02d:%02d",
timeCreation.GetMonth(),
timeCreation.GetDay(),
timeCreation.GetYear(),
timeCreation.GetHour(),
timeCreation.GetMinute(),
timeCreation.GetSecond());
m_lcProcessInfo.SetItemText(nItem, 2, strData);
timeDiff = timeNow - timeCreation;
strData.Format("%ud,%uh,%um,%us", timeDiff.GetDays(), timeDiff.GetHours(), timeDiff.GetMinutes(), timeDiff.GetSeconds());
m_lcProcessInfo.SetItemText(nItem, 3, strData);
FileTimeToSystemTime(&ftKernel, &stKernel);
strData.Format("%uh,%um,%us", stKernel.wHour, stKernel.wMinute, stKernel.wSecond);
m_lcProcessInfo.SetItemText(nItem, 4, strData);
FileTimeToSystemTime(&ftUser, &stUser);
strData.Format("%uh,%um,%us", stUser.wHour, stUser.wMinute, stUser.wSecond);
m_lcProcessInfo.SetItemText(nItem, 5, strData);
}
else
TRACE("GetProcessTimes() failed: %s\n", GetErrorMessage());
}
else
TRACE("GetModuleBaseName() failed: %s\n", GetErrorMessage());
}
else
TRACE2("EnumProcessModules() failed on PID %#x: %s\n", dwProcessIDs[nIndex], GetErrorMessage());
CloseHandle(hProcess);
}
else
TRACE2("OpenProcess(%#x) failed: %s\n", dwProcessIDs[nIndex], GetErrorMessage());
}
}
else
TRACE("EnumProcesses() failed: %s\n", GetErrorMessage());
}
用于返回错误信息的函数GetErrorMessage(),具体实现代码如下。
CString CProcessTimeDlg::GetErrorMessage()
{
CString strError;
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL);
strError = (LPTSTR) lpMsgBuf;
LocalFree(lpMsgBuf);
return (strError);
}
返回指定模块基本名称的函数GetModuleBaseNames(),具体实现代码如下。
DWORD CProcessTimeDlg::GetModuleBaseNames(const HANDLE hProcess, const HMODULE hModule, CString &strName)
{
DWORD dwLength;
dwLength = ::GetModuleBaseName(hProcess, hModule, strName.GetBuffer(MAX_PATH), MAX_PATH);
strName.ReleaseBuffer();
return (dwLength);
}
以上就是实例的关键实现代码,使用时直接调用Process函数即可。注意先在自己的项目中包含psapi.h头文件。