四种方法实现VC枚举系统当前进程(2)
下面是第二种方法的实现过程:首先,先把Psapi.dll里要用到函数都定义好,方便后面显示调用。
//在psaipi.dll中的函数EnumProcesses用来枚举进程
typedef BOOL (_stdcall *ENUMPROCESSES)( //注意这里要指明调用约定为-stdcall
DWORD* pProcessIds, //指向进程ID数组链
DWORD cb, //ID数组的大小,用字节计数
DWORD* pBytesReturned); //返回的字节
//在psapi.dll中的函数EnumProcessModules用来枚举进程模块
typedef BOOL (_stdcall *ENUMPROCESSMODULES)(
HANDLE hProcess, //进程句柄
HMODULE* lphModule, //指向模块句柄数组链
DWORD cb, //模块句柄数组大小,字节计数
LPDWORD lpcbNeeded); //存储所有模块句柄所需的字节数
//在psapi.dll中的函数GetModuleFileNameEx获得进程模块名
typedef DWORD (_stdcall *GETMODULEFILENAMEEX)(
HANDLE hProcess, //进程句柄
HMODULE hModule, //进程句柄
LPTSTR lpFilename, //存放模块全路径名
DWORD nSize //lpFilename缓冲区大小,字符计算
);
好,通过每个定义的函数前的注释你可以清楚看到这些原函数名,然后当然要加载包含这些函数模块Psapi.dll啦:
hPsDll = LoadLibrary("PSAPI.DLL");
接着,通过Dll入口,我们查找每个函数地址:
pEnumProcesses =
(ENUMPROCESSES)GetProcAddress(hPsDll, "EnumProcesses");
pEnumProcessModules =
(ENUMPROCESSMODULES)GetProcAddress(hPsDll, "EnumProcessModules");
pGetModuleFileNameEx =
(GETMODULEFILENAMEEX)GetProcAddress(hPsDll, "GetModuleFileNameExA");
注意第三个函数名GetModuleFileNameExA,在Dll里有以A和W结尾区分函数,A指采用的是ANSI字符串方式,W则是UNICODE方式。于是,我们可以用下面的语句枚举进程:
pEnumProcesses(processid, sizeof(processid), &needed);
processcount=needed/sizeof(DWORD);
for (i=0;i<processcount;i++)
{
//打开进程
hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
false, processid[i]);
if (hProcess)
{
pEnumProcessModules(hProcess, &hModule, sizeof(hModule), &needed);
pGetModuleFileNameEx(hProcess, hModule, path, sizeof(path));
GetShortPathName(path,path,256);
itoa(processid[i],temp,10);
printf("%s --- %s
",path,temp);
}
else
printf("Failed!!!
");
}
当然,在Google上一搜索,可以找到不少提供的Psapi.h头文件和对应的Psapi.lib库,这样,你就可以更方便用这种方法了。