WIN32汇编语言教程:第13章 进程控制 · 13.3 进程调试(2)
汇编源文件ProcessList.asm的内容如下:
.386
.model flat, stdcall
option casemap :none
;####################################################################
; Include 文件定义
;####################################################################
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;####################################################################
; Equ 等值定义
;####################################################################
ICO_MAIN equ 1000
DLG_MAIN equ 1000
IDC_PROCESS equ 1001
IDC_REFRESH equ 1002
;####################################################################
; 数据段
;####################################################################
.data?
hInstance dd ?
hWinList dd ?
.const
szErrTerminate db '无法结束指定进程!',0
;####################################################################
; 代码段
;####################################################################
.code
;####################################################################
_GetProcessList proc _hWnd
local @stProcess:PROCESSENTRY32
local @hSnapShot
invoke RtlZeroMemory,addr @stProcess,sizeof @stProcess
invoke SendMessage,hWinList,LB_RESETCONTENT,0,0
mov @stProcess.dwSize,sizeof @stProcess
invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0
mov @hSnapShot,eax
invoke Process32First,@hSnapShot,addr @stProcess
.while eax
invoke SendMessage,hWinList,LB_ADDSTRING,\
0,addr @stProcess.szExeFile
invoke SendMessage,hWinList,LB_SETITEMDATA,eax,\
@stProcess.th32ProcessID
invoke Process32Next,@hSnapShot,addr @stProcess
.endw
invoke CloseHandle,@hSnapShot
invoke GetDlgItem,_hWnd,IDOK
invoke EnableWindow,eax,FALSE
ret
_GetProcessList endp
;####################################################################
_ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam
mov eax,wMsg
.if eax == WM_CLOSE
invoke EndDialog,hWnd,NULL
.elseif eax == WM_INITDIALOG
invoke GetDlgItem,hWnd,IDC_PROCESS
mov hWinList,eax
invoke _GetProcessList,hWnd
;********************************************************************
.elseif eax == WM_COMMAND
mov eax,wParam
.if ax == IDOK
invoke SendMessage,hWinList,LB_GETCURSEL,0,0
invoke SendMessage,hWinList,\
LB_GETITEMDATA,eax,0
invoke OpenProcess,PROCESS_TERMINATE,\
FALSE,eax
.if eax
mov ebx,eax
invoke TerminateProcess,ebx,-1
invoke CloseHandle,ebx
invoke Sleep,200
invoke _GetProcessList,hWnd
jmp @F
.endif
invoke MessageBox,hWnd,addr szErrTerminate,\
NULL,MB_OK or MB_ICONWARNING
@@:
;********************************************************************
.elseif ax == IDC_REFRESH
invoke _GetProcessList,hWnd
;********************************************************************
.elseif ax == IDC_PROCESS
shr eax,16
.if ax == LBN_SELCHANGE
invoke GetDlgItem,hWnd,IDOK
invoke EnableWindow,eax,TRUE
.endif
.endif
;********************************************************************
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
;####################################################################
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,DLG_MAIN,\
NULL,offset _ProcDlgMain,NULL
invoke ExitProcess,NULL
;####################################################################
end start
程序在初始化、按下“刷新”按钮以及结束一个线程以后都要调用_GetProcessList子程序来重新获取系统中运行的进程列表。在_GetProcessList子程序中,程序首先向列表框发送LB_RESETCONTENT消息删除原来的列表内容,并调用CreateToolhelp32Snapshot函数获得一个快照。函数的使用格式是:
invoke CreateToolhelp32Snapshot,dwFlags,th32ProcessID
.if eax
mov hSnapShot,eax
.endif
dwFlags参数用来指定“快照”中需要返回的对象,本函数不仅可以获取进程列表,也可以用来获取线程和模块等对象的列表,参数可以指定的值是:
● TH32CS_SNAPHEAPLIST——对指定进程中的堆进行枚举。
● TH32CS_SNAPMODULE——对指定进程中的模块进行枚举。
● TH32CS_SNAPPROCESS——对系统范围中的进程进行枚举。
● TH32CS_SNAPTHREAD——对系统范围中的线程进行枚举。
th32ProcessID参数用来指定一个进程ID,当dwFlags指定为TH32CS_SNAPHEAPLIST或者TH32CS_SNAPMODULE来枚举某个进程中的堆以及模块的时候,这个参数用来指定被枚举的进程ID。对于TH32CS_SNAPPROCESS和TH32CS_SNAPTHREAD标志,由于枚举的范围是系统范围内的,所以th32ProcessID参数将被忽略。
如果函数执行成功,将返回一个快照句柄,否则返回−1。程序可以通过这个快照句柄获取进程列表。
从快照句柄中获取进程参数使用Process32First和Process32Next函数,函数的每次调用仅返回一个进程的信息。Process32First函数用来进行首次调用,以后的调用由Process32Next函数循环完成,直到所有的进程信息都被获取为止,当不再有剩余信息的时候,函数返回FALSE,所以一般使用下面的循环结构来获取进程列表: