如何找出系统上正在运行的任务
说明:此篇文章来自网易,不过我看好象是<Win95API开发人员指南>上的,也不知那位仁兄输入的,不过众网友会感激他的
问题
有的程序员希望能够向用户列出当前正在运行的任务,但对任务和窗口的区
别又不是很确定。是否可以同时列出呢?还是需要确定显示哪一个呢?
方法
列出任务和窗口是相当有用的。任务是运行着的 Windows 应用程序,无论此
应用程序是否显示窗口。一个任务也可以显示好几个窗口,主窗口即父窗口,其
它的窗口为父窗口的子窗口,子窗口通常显示在父窗口内,但也可以显示在父窗
口外。无论是显示在父窗口内还是显示在父窗口外,所有的子窗口都同属于这一
个任务。
步骤
按照下列步骤实现一个例子程序。运行此例子程序,从菜单 Tasks 中选择菜
单项 View Tasks,弹出对话框,对话框含有一个列表框和四个按钮,选择按钮
Process,在列表框中将显示出所有当前正在运行的任务的名字。
并非所有的任务都显示窗口。选择第二个按钮 Windows,列表框中将显示出
所有当前正在运行的窗口的名字。选择按钮 Modules,列表框中将显示出所有已
装入的模块。按钮 Close 用来关闭对话框。
实现例子程序的具体步骤如下:
1.在 Visual C++ 中,利用 AppWizard 创建新的项目文件,并命名此项目文
件为 LD31.MAK.
2.进入 AppStudio 并创建新的对话框。添加一个列表框和三个按钮,按钮的
标题分别为 Processes、Windows 和 Modules,ID 分别为 ID_PROCESS_LIST、I
D_WINDOW_LIST 和 ID_MODULE_LIST。改变按钮 OK 的标题为 Close,删除 Canc
el 按钮。将对话框的标题改为 Application List。
3.进入 ClassWizard 为此对话框生成新的对话框类,类名为 CTaskDlg。从
对象列表中选择 CTaskDlg,从消息列表中选择消息 WM_INITDIALOG。点击按钮
Add Function,在方法 OnInitDialog 中输入下列代码:
BOOL CTaskDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CenterWindow();
if(!InitToolhelp32())
{
MessageBox("Unable to initialize toolhelp functions!",
"Error",MB_OK|MB_ICONSTOP);
EndDialog(IDCANCEL);
return FALSE;
}
return TRUE; // return TRUE unless you set the focus to a control
}
4.从对象列表中选择 ID_PROCESS_LIST,从消息列表中选择消息 BN_CLICKE
D,命名方法为 OnProcessList,并在此方法中添加下列代码:
void CTaskDlg::OnProcessList()
{
HANDLE hSnapshot=pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
PROCESSENTRY32 pe;
if(!hSnapshot)
return;
CListBox * list=(CListBox *)GetDlgItem(IDC_LIST1);
list->ResetContent();
pe.dwSize=sizeof(pe);
for(int i=pProcess32First(hSnapshot,&pe);i;
i=pProcess32Next(hSnapshot,&pe))
{
HANDLE hModuleSnap=NULL;
MODULEENTRY32 me;
hModuleSnap=pCreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
pe.th32ProcessID);
if(hModuleSnap==(HANDLE)(-1))
return;
me.dwSize=sizeof(MODULEENTRY32);
if(pModule32First(hModuleSnap,&me))
{
do
{
if(me.th32ModuleID==pe.th32ModuleID)
{
list->AddString(me.szExePath);
break;
}
}while(pModule32Next(hModuleSnap,&me));
}
}
CloseHandle(hSnapshot);
}
5.从对象列表中选择 ID_WINDOW_LIST,从消息列表中选择消息 BN_CLICKED
,命名方法为 OnWindowList,并在此方法中添加下列代码:
void CTaskDlg::OnWindowList()
{
CListBox * list=(CListBox *)GetDlgItem(IDC_LIST1);
list->ResetContent();
FARPROC EnumProcInstance=MakeProcInstance(
(FARPROC)EnumWindowsProc,AfxGetInstanceHandle());
EnumWindows((WNDENUMPROC)EnumProcInstance,(LPARAM)list);
FreeProcInstance(EnumProcInstance);
UpdateData();
}
6.在方法 OnWindowList 的前面添加下列代码:
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
CListBox * list=(CListBox *)lParam;
char buf[256];
GetWindowText(hwnd,buf,256);
if(strlen(buf))
list->AddString(buf);
return TRUE;
}
7.从对象列表中选择 ID_MODULE_LIST,从消息列表中选择消息 BN_CLICKED
,命名方法为 OnModuleList,并在此方法中添加下列代码:
void CTaskDlg::OnModuleList()
{
MODULEENTRY32 me;
CListBox * list=(CListBox *)GetDlgItem(IDC_LIST1);
list->ResetContent();
memset(&me,0,sizeof(me));
me.dwSize=sizeof(MODULEENTRY32);
HANDLE hSnapshot=pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(!hSnapshot)
return;
for(int i=pModule32First(hSnapshot,&me);i;
i=pModule32Next(hSnapshot,&me))
list->AddString(me.szExePath);
CloseHandle(hSnapshot);
}
8.在文件 TaskDlg.cpp 的顶部添加如下代码:
typedef BOOL (WINAPI * MODULEWALK)(HANDLE hSnapshot,
LPMODULEENTRY32 lpme);
typedef BOOL (WINAPI * THREADWALK)(HANDLE hSnapshot,
LPTHREADENTRY32 lpte);
typedef BOOL (WINAPI * PROCESSWALK)(HANDLE hSnapshot,
LPPROCESSENTRY32 lppe);
typedef HANDLE (WINAPI * CREATESNAPSHOT)(DWORD dwFlags,
DWORD th32ProcessID);
static CREATESNAPSHOT pCreateToolhelp32Snapshot=NULL;
static MODULEWALK pModule32First=NULL;
static MODULEWALK pModule32Next=NULL;
static PROCESSWALK pProcess32First=NULL;
static PROCESSWALK pProcess32Next=NULL;
static THREADWALK pThread32First=NULL;
static THREADWALK pThread32Next=NULL;
BOOL InitToolhelp32(void)
{
BOOL bRet=FALSE;
HINSTANCE hKernel=NULL;
hKernel=GetModuleHandle("KERNEL32.DLL");
if(hKernel)
{
pCreateToolhelp32Snapshot=
(CREATESNAPSHOT)GetProcAddress(hKernel,
"CreateToolhelp32Snapshot");
pModule32First=(MODULEWALK)GetProcAddress(hKernel,
"Module32First");
pModule32Next=(MODULEWALK)GetProcAddress(hKernel,
"Module32Next");
pProcess32First=(PROCESSWALK)GetProcAddress(hKernel,
"Process32First");
pProcess32Next=(PROCESSWALK)GetProcAddress(hKernel,
"Process32Next");
pThread32First=(THREADWALK)GetProcAddress(hKernel,
"Thread32First");
pThread32Next=(THREADWALK)GetProcAddress(hKernel,
"Thread32Next");
bRet=pModule32First&&pModule32Next&&pProcess32First&&
pProcess32Next&&pThread32First&&pThread32Next&&
pCreateToolhelp32Snapshot;
}
else
bRet=FALSE;
return bRet;
}
9.最后,在文件 TaskDlg.cpp 的顶部添加下列行:
#include"tlhelp32.h"
10.进入 AppStudio,在菜单 IDR_WAINFRAME 中添加新的菜单 Tasks.在 T
asks 中添加新的菜单项 View Tasks,ID 命名为 ID_VIEW_TASKS。
11.启动 ClassWizard.从下拉列表中选择对象 CMainFrame,从对象列表中
选择 ID_VIEW_TASKS,选择消息 COMMAND,点击按钮 Add Function,方法命名为
OnViewTasks。
12.在 CMainFrame 的成员函数 OnViewTasks 中输入下列代码:
void CMainFrame::OnViewTasks()
{
CTaskDlg dlg;
dlg.DoModal();
}
13.在文件 MAINFRM.CPP 的顶部添加下列行:
#include "TaskDlg.h"
14.编译并运行此例子程序。
注释
本节介绍了三个不同的 Windows API 函数集,用来列出当前正在运行的任务
、正在运行的窗口和已装入的 DLL。
Windows 9x API 函数 Process32First 和 Process32Next,用来列出当前正
在运行的进程。要使用这些函数,必须从 kernel32.DLL 中装入这些函数,从而
完成 ToolHelp 功能的初始化,函数 InitToolhelp32 即用来完成 TollHelp 功
能的初始化。这些 API 函数将遍历进程链表,返回每一个进程的进程标识符,调
用模块函数(Module32First 和 Module32Next)遍历模块链表,从而找出相应的
进程名。
Windows API 函数 MakeProcInstance 和 EnumWindows,用来列出当前正在
运行的窗口。在例子程序中,函数 MakeProcInstance 接受函数 EnumWindowsPr
oc 的地址,返回 FARPROC 类型的值,接着使用函数 EnumWindows 将此返回值传
送给 Windows,从而列出所有的主窗口。函数 EnumWindowsProc 具有两个参数,
第一个参数为窗口句柄,第二个参数为用户定义参数,由函数 EnumWindows 传送
。在本节的例子中,此参数为 CListBox 的实例,用来存储数据。在函数 EnumW
indowsProc(因被 Windows 调用,所以也称回调函数)中,窗口的标题显示在列
表框中,以便于用户查看。
说明:此篇文章来自网易,不过我看好象是<Win95API开发人员指南>上的,也不知那位仁兄输入的,不过众网友会感激他的
问题
有的程序员希望能够向用户列出当前正在运行的任务,但对任务和窗口的区
别又不是很确定。是否可以同时列出呢?还是需要确定显示哪一个呢?
方法
列出任务和窗口是相当有用的。任务是运行着的 Windows 应用程序,无论此
应用程序是否显示窗口。一个任务也可以显示好几个窗口,主窗口即父窗口,其
它的窗口为父窗口的子窗口,子窗口通常显示在父窗口内,但也可以显示在父窗
口外。无论是显示在父窗口内还是显示在父窗口外,所有的子窗口都同属于这一
个任务。
步骤
按照下列步骤实现一个例子程序。运行此例子程序,从菜单 Tasks 中选择菜
单项 View Tasks,弹出对话框,对话框含有一个列表框和四个按钮,选择按钮
Process,在列表框中将显示出所有当前正在运行的任务的名字。
并非所有的任务都显示窗口。选择第二个按钮 Windows,列表框中将显示出
所有当前正在运行的窗口的名字。选择按钮 Modules,列表框中将显示出所有已
装入的模块。按钮 Close 用来关闭对话框。
实现例子程序的具体步骤如下:
1.在 Visual C++ 中,利用 AppWizard 创建新的项目文件,并命名此项目文
件为 LD31.MAK.
2.进入 AppStudio 并创建新的对话框。添加一个列表框和三个按钮,按钮的
标题分别为 Processes、Windows 和 Modules,ID 分别为 ID_PROCESS_LIST、I
D_WINDOW_LIST 和 ID_MODULE_LIST。改变按钮 OK 的标题为 Close,删除 Canc
el 按钮。将对话框的标题改为 Application List。
3.进入 ClassWizard 为此对话框生成新的对话框类,类名为 CTaskDlg。从
对象列表中选择 CTaskDlg,从消息列表中选择消息 WM_INITDIALOG。点击按钮
Add Function,在方法 OnInitDialog 中输入下列代码:
BOOL CTaskDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CenterWindow();
if(!InitToolhelp32())
{
MessageBox("Unable to initialize toolhelp functions!",
"Error",MB_OK|MB_ICONSTOP);
EndDialog(IDCANCEL);
return FALSE;
}
return TRUE; // return TRUE unless you set the focus to a control
}
4.从对象列表中选择 ID_PROCESS_LIST,从消息列表中选择消息 BN_CLICKE
D,命名方法为 OnProcessList,并在此方法中添加下列代码:
void CTaskDlg::OnProcessList()
{
HANDLE hSnapshot=pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
PROCESSENTRY32 pe;
if(!hSnapshot)
return;
CListBox * list=(CListBox *)GetDlgItem(IDC_LIST1);
list->ResetContent();
pe.dwSize=sizeof(pe);
for(int i=pProcess32First(hSnapshot,&pe);i;
i=pProcess32Next(hSnapshot,&pe))
{
HANDLE hModuleSnap=NULL;
MODULEENTRY32 me;
hModuleSnap=pCreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
pe.th32ProcessID);
if(hModuleSnap==(HANDLE)(-1))
return;
me.dwSize=sizeof(MODULEENTRY32);
if(pModule32First(hModuleSnap,&me))
{
do
{
if(me.th32ModuleID==pe.th32ModuleID)
{
list->AddString(me.szExePath);
break;
}
}while(pModule32Next(hModuleSnap,&me));
}
}
CloseHandle(hSnapshot);
}
5.从对象列表中选择 ID_WINDOW_LIST,从消息列表中选择消息 BN_CLICKED
,命名方法为 OnWindowList,并在此方法中添加下列代码:
void CTaskDlg::OnWindowList()
{
CListBox * list=(CListBox *)GetDlgItem(IDC_LIST1);
list->ResetContent();
FARPROC EnumProcInstance=MakeProcInstance(
(FARPROC)EnumWindowsProc,AfxGetInstanceHandle());
EnumWindows((WNDENUMPROC)EnumProcInstance,(LPARAM)list);
FreeProcInstance(EnumProcInstance);
UpdateData();
}
6.在方法 OnWindowList 的前面添加下列代码:
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
CListBox * list=(CListBox *)lParam;
char buf[256];
GetWindowText(hwnd,buf,256);
if(strlen(buf))
list->AddString(buf);
return TRUE;
}
7.从对象列表中选择 ID_MODULE_LIST,从消息列表中选择消息 BN_CLICKED
,命名方法为 OnModuleList,并在此方法中添加下列代码:
void CTaskDlg::OnModuleList()
{
MODULEENTRY32 me;
CListBox * list=(CListBox *)GetDlgItem(IDC_LIST1);
list->ResetContent();
memset(&me,0,sizeof(me));
me.dwSize=sizeof(MODULEENTRY32);
HANDLE hSnapshot=pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(!hSnapshot)
return;
for(int i=pModule32First(hSnapshot,&me);i;
i=pModule32Next(hSnapshot,&me))
list->AddString(me.szExePath);
CloseHandle(hSnapshot);
}
8.在文件 TaskDlg.cpp 的顶部添加如下代码:
typedef BOOL (WINAPI * MODULEWALK)(HANDLE hSnapshot,
LPMODULEENTRY32 lpme);
typedef BOOL (WINAPI * THREADWALK)(HANDLE hSnapshot,
LPTHREADENTRY32 lpte);
typedef BOOL (WINAPI * PROCESSWALK)(HANDLE hSnapshot,
LPPROCESSENTRY32 lppe);
typedef HANDLE (WINAPI * CREATESNAPSHOT)(DWORD dwFlags,
DWORD th32ProcessID);
static CREATESNAPSHOT pCreateToolhelp32Snapshot=NULL;
static MODULEWALK pModule32First=NULL;
static MODULEWALK pModule32Next=NULL;
static PROCESSWALK pProcess32First=NULL;
static PROCESSWALK pProcess32Next=NULL;
static THREADWALK pThread32First=NULL;
static THREADWALK pThread32Next=NULL;
BOOL InitToolhelp32(void)
{
BOOL bRet=FALSE;
HINSTANCE hKernel=NULL;
hKernel=GetModuleHandle("KERNEL32.DLL");
if(hKernel)
{
pCreateToolhelp32Snapshot=
(CREATESNAPSHOT)GetProcAddress(hKernel,
"CreateToolhelp32Snapshot");
pModule32First=(MODULEWALK)GetProcAddress(hKernel,
"Module32First");
pModule32Next=(MODULEWALK)GetProcAddress(hKernel,
"Module32Next");
pProcess32First=(PROCESSWALK)GetProcAddress(hKernel,
"Process32First");
pProcess32Next=(PROCESSWALK)GetProcAddress(hKernel,
"Process32Next");
pThread32First=(THREADWALK)GetProcAddress(hKernel,
"Thread32First");
pThread32Next=(THREADWALK)GetProcAddress(hKernel,
"Thread32Next");
bRet=pModule32First&&pModule32Next&&pProcess32First&&
pProcess32Next&&pThread32First&&pThread32Next&&
pCreateToolhelp32Snapshot;
}
else
bRet=FALSE;
return bRet;
}
9.最后,在文件 TaskDlg.cpp 的顶部添加下列行:
#include"tlhelp32.h"
10.进入 AppStudio,在菜单 IDR_WAINFRAME 中添加新的菜单 Tasks.在 T
asks 中添加新的菜单项 View Tasks,ID 命名为 ID_VIEW_TASKS。
11.启动 ClassWizard.从下拉列表中选择对象 CMainFrame,从对象列表中
选择 ID_VIEW_TASKS,选择消息 COMMAND,点击按钮 Add Function,方法命名为
OnViewTasks。
12.在 CMainFrame 的成员函数 OnViewTasks 中输入下列代码:
void CMainFrame::OnViewTasks()
{
CTaskDlg dlg;
dlg.DoModal();
}
13.在文件 MAINFRM.CPP 的顶部添加下列行:
#include "TaskDlg.h"
14.编译并运行此例子程序。
注释
本节介绍了三个不同的 Windows API 函数集,用来列出当前正在运行的任务
、正在运行的窗口和已装入的 DLL。
Windows 9x API 函数 Process32First 和 Process32Next,用来列出当前正
在运行的进程。要使用这些函数,必须从 kernel32.DLL 中装入这些函数,从而
完成 ToolHelp 功能的初始化,函数 InitToolhelp32 即用来完成 TollHelp 功
能的初始化。这些 API 函数将遍历进程链表,返回每一个进程的进程标识符,调
用模块函数(Module32First 和 Module32Next)遍历模块链表,从而找出相应的
进程名。
Windows API 函数 MakeProcInstance 和 EnumWindows,用来列出当前正在
运行的窗口。在例子程序中,函数 MakeProcInstance 接受函数 EnumWindowsPr
oc 的地址,返回 FARPROC 类型的值,接着使用函数 EnumWindows 将此返回值传
送给 Windows,从而列出所有的主窗口。函数 EnumWindowsProc 具有两个参数,
第一个参数为窗口句柄,第二个参数为用户定义参数,由函数 EnumWindows 传送
。在本节的例子中,此参数为 CListBox 的实例,用来存储数据。在函数 EnumW
indowsProc(因被 Windows 调用,所以也称回调函数)中,窗口的标题显示在列
表框中,以便于用户查看。