遍历进程并获取进程路径
代码文件:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses PsAPI;
procedure TForm1.Button1Click(Sender: TObject);
const
n = 512;
var
IDArr: array[0..n-1] of DWORD;
size,i: DWORD;
buf: array[0..MAX_PATH] of Char;
pHandle: THandle;
begin
// FillChar(buf, n, #0); {这样可避免乱码}
EnumProcesses(@IDArr, n, size);
for i := 0 to size div SizeOf(DWORD) - 1 do
begin
pHandle := OpenProcess(PROCESS_ALL_ACCESS, False, IDArr[i]);
GetModuleFileNameEx(pHandle, 0, buf, Length(buf)*SizeOf(buf[0]));
CloseHandle(pHandle);
Memo1.Lines.Add(buf);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Clear;
Memo1.Align := alTop;
Memo1.ScrollBars := ssBoth;
end;
end.
窗体文件:
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 206
ClientWidth = 447
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 342
Top = 173
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object Memo1: TMemo
Left = 24
Top = 8
Width = 185
Height = 161
Lines.Strings = (
'Memo1')
TabOrder = 1
end
end
本例效果图:
代码文件:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses PsAPI; {GetModuleFileNameEx 函数需要它}
{根据窗口句柄获取所在程序路径的函数}
function GetProcessExePath(h: HWND): string;
var
pid: Cardinal;
pHandle: THandle;
buf: array[0..MAX_PATH] of Char;
begin
{先获取进程 ID}
GetWindowThreadProcessId(h, @pid);
{再获取进程句柄}
pHandle := OpenProcess(PROCESS_ALL_ACCESS, False, pid);
{获取进程路径}
GetModuleFileNameEx(pHandle, 0, buf, Length(buf));
CloseHandle(pHandle);
Result := buf;
end;
{测试当前程序}
procedure TForm1.Button1Click(Sender: TObject);
var
path: string;
begin
path := GetProcessExePath(Handle);
ShowMessage(path);
end;
{测试记事本 - 需要随便打开一个记事本}
procedure TForm1.Button2Click(Sender: TObject);
var
wh: HWND;
path: string;
begin
wh := FindWindow('Notepad', nil);
path := GetProcessExePath(wh);
ShowMessage(path);
end;
end.
窗体文件:
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 116
ClientWidth = 471
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
Position = poDesktopCenter
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 112
Top = 33
Width = 233
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object Button2: TButton
Left = 112
Top = 64
Width = 233
Height = 25
Caption = 'Button2'
TabOrder = 1
OnClick = Button2Click
end
end
GetModuleFileName、GetModuleHandle
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
buf: array[0..MAX_PATH] of Char;
hinst: HMODULE;
begin
{获取指定模块的句柄}
hinst := GetModuleHandle('gdi32.dll');
{获取模块的路径}
GetModuleFileName(hinst, buf, Length(buf));
ShowMessage(buf); {C:\WINDOWS\system32\GDI32.dll}
end;
procedure TForm1.Button1Click(Sender: TObject);
var
buf: array[0..MAX_PATH] of Char;
begin
{当 GetModuleFileName 的第一个参数为 0 或 HInstance 时, 会获取当前模块路径}
GetModuleFileName(0, buf, Length(buf));
ShowMessage(buf);
GetModuleFileName(HInstance, buf, Length(buf));
ShowMessage(buf);
{获取当前程序路径的常用方法}
ShowMessage(Application.ExeName);
ShowMessage(ParamStr(0));
end;
end.
GetModuleHandle - 获取一个模块(exe 或 dll)的句柄
定义:
GetModuleHandle(
lpModuleName: PChar {模块名; 只能是映射到当前进程的模块}
): HMODULE; {返回模块句柄; 0 表示失败}
举例:
//获取当前模块的句柄
var
s: string;
h: Cardinal;
begin
{先取得模块名}
s := Application.ExeName;
s := ExtractFileName(s);
{获取参数只要模块名就够了; 不需要路径(测试中有路径也可以)}
h := GetModuleHandle(PChar(s));
ShowMessage(IntToStr(h)); {4194304}
end;
//用 nil 做参数即可获取当前模块的句柄
var
h: Cardinal;
begin
h := GetModuleHandle(nil);
ShowMessage(IntToStr(h)); {4194304}
end;
//获取系统骨干模块 Gdi32.dll 的句柄
var
h: Cardinal;
begin
h := GetModuleHandle('Gdi32.dll');
ShowMessage(IntToStr(h)); {2012151808}
end;
//能不能获取记事本的句柄?
var
h: Cardinal;
begin
h := GetModuleHandle('notepad.exe');
ShowMessage(IntToStr(h)); {0; 失败}
{因为当前进程和记事本的进程是相互独立的; }
{如果用能够冲破进程、面向全局的 dll 应该可以.}
end;
OpenProcess、GetExitCodeProcess、TerminateProcess (测试强制关闭 OICQ)
/声明:
{返回进程的句柄}
OpenProcess(
dwDesiredAccess: DWORD; {访问选项}
bInheritHandle: BOOL; {能否继承; True 表示能用 CreateProcess 继承句柄创建新进程}
dwProcessId: DWORD {指定进程 ID}
): THandle; {成功会返回进程句柄; 失败返回 0}
//dwDesiredAccess 可选值:
PROCESS_TERMINATE = $0001; {允许 TerminateProcess 使用进程句柄来关闭进程}
PROCESS_CREATE_THREAD = $0002; {允许 CreateRemoteThread 使用进程句柄来创建线程}
PROCESS_VM_OPERATION = $0008; {允许 VirtualProtectEx 使用进程句柄来改变进程的虚拟内存}
PROCESS_VM_READ = $0010; {允许 ReadProcessMemory 使用进程句柄从进程的虚拟内存中读取数据}
PROCESS_VM_WRITE = $0020; {允许 WriteProcessMemory 使用进程句柄向进程的虚拟内存中写入数据}
PROCESS_DUP_HANDLE = $0040; {允许 DuplicateHandle 把进程句柄当作源句柄或目标句柄进行复制}
PROCESS_CREATE_PROCESS = $0080; {默认值}
PROCESS_SET_QUOTA = $0100; {允许 SetProcessWorkingSetSize 使用进程句柄来来设置虚拟内存的上限值}
PROCESS_SET_INFORMATION = $0200; {允许 SetPriorityClass 使用进程句柄来设置进程优先级}
PROCESS_QUERY_INFORMATION = $0400; {允许 GetExitCodeProcess 或 GetPriorityClass 通过进程句柄读取进程信息}
SYNCHRONIZE = $00100000; {允许任何等待的函数使用进程句柄}
PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $FFF); {允许所有权限}
{获取指定进程的退出码}
GetExitCodeProcess(
hProcess: THandle; {进程句柄}
var lpExitCode: DWORD {接收退出码}
): BOOL; {}
{强制结束(其他)进程}
TerminateProcess(
hProcess: THandle; {进程句柄}
uExitCode: UINT {退出码}
): BOOL; {}
//提示: 关闭其他程序一般应该是向其主窗口发送 WM_CLOSE 消息, 不行再用这个, 因为它不能关闭其关联的 DLL.
//举例(强行关闭 OICQ 的办法):
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
id: Cardinal;
wh: HWND;
ph: THandle;
ExitCode: DWORD;
begin
wh := FindWindow('#32770', nil);
GetWindowThreadProcessId(wh, id);
ph := OpenProcess(PROCESS_TERMINATE, False, id);
GetExitCodeProcess(ph, ExitCode);
TerminateProcess(ph, ExitCode);
end;
end.
GetWindowThreadProcessId - 获取指定窗口的进程 ID 或线程 ID
//声明:
GetWindowThreadProcessId(
hWnd: HWND; {指定窗口句柄}
lpdwProcessId: Pointer = nil {返回进程 ID 的指针}
): DWORD; {返回线程 ID}
//举例:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
c: Cardinal;
begin
GetWindowThreadProcessId(Handle, @c);
ShowMessage(IntToStr(c)); {2792; 随机的}
{在本例中相同于 GetCurrentProcessID 的结果}
c := GetCurrentProcessID;
ShowMessage(IntToStr(c)); {2792}
c := GetWindowThreadProcessId(Handle, nil);
ShowMessage(IntToStr(c)); {2748}
{在本例中相同于 GetCurrentThreadID 的结果}
c := GetCurrentThreadID;
ShowMessage(IntToStr(c)); {2748}
end;
end.
GetCurrentThread、GetCurrentThreadId、GetCurrentProcess、GetCurrentProcessId
{返回当前线程的虚拟句柄}
GetCurrentThread: THandle;
{返回当前线程 ID}
GetCurrentThreadId: DWORD;
{返回当前进程的虚拟句柄}
GetCurrentProcess: THandle;
{返回当前进程 ID}
GetCurrentProcessId: DWORD;
提示:
ID 是系统唯一的标识.
所谓虚拟句柄, 就是该句柄只在调用进程的进程中有效, 也不能被继承;
如果用于其他进程需要用 DuplicateHandle 复制句柄;
GetCurrentProcess 返回的虚拟句柄可以通过 OpenProcess 创建一个真实的句柄.
举例:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids;
type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
StringGrid1.Cells[0,0] := '当前线程虚拟句柄: ';
StringGrid1.Cells[0,1] := '当前线程 ID: ';
StringGrid1.Cells[0,2] := '当前进程虚拟句柄: ';
StringGrid1.Cells[0,3] := '当前进程 ID: ';
StringGrid1.Cells[1,0] := IntToStr(GetCurrentThread);
StringGrid1.Cells[1,1] := IntToStr(GetCurrentThreadID);
StringGrid1.Cells[1,2] := IntToStr(GetCurrentProcess);
StringGrid1.Cells[1,3] := IntToStr(GetCurrentProcessId);
{下面是显示格式的调整}
StringGrid1.Align := alClient;
StringGrid1.FixedRows := 0;
StringGrid1.RowCount := 4;
StringGrid1.ColCount := 2;
StringGrid1.ColWidths[0] := StringGrid1.Canvas.TextWidth(StringGrid1.Cells[0,0]) + 4;
StringGrid1.ColWidths[1] := StringGrid1.Canvas.TextWidth(StringGrid1.Cells[0,1]) + 4;
end;
end.
//效果图:
LoadLibrary、FreeLibrary - 载入与载卸模块
//声明:
LoadLibrary( {将可执行模块映射到调用进程的地址空间}
lpLibFileName: PChar {DLL 或 EXE 文件名; 如没指定路径会按以下顺序查找: 程序目录/当前目录/System32/Windows/PATH环境变量}
): HMODULE; {返回模块句柄}
FreeLibrary(
hLibModule: HMODULE {模块句柄}
): BOOL;
ShellExecute(
hWnd: HWND; {指定父窗口句柄}
Operation: PChar; {指定动作, 譬如: open、print}
FileName: PChar; {指定要打开的文件或程序}
Parameters: PChar; {给要打开的程序指定参数; 如果打开的是文件这里应该是 nil}
Directory: PChar; {缺省目录}
ShowCmd: Integer {打开选项}
): HINST; {执行成功会返回应用程序句柄; 如果这个值 <= 32, 表示执行错误}
//返回值可能的错误有:
= 0 {内存不足}
ERROR_FILE_NOT_FOUND = 2; {文件名错误}
ERROR_PATH_NOT_FOUND = 3; {路径名错误}
ERROR_BAD_FORMAT = 11; {EXE 文件无效}
SE_ERR_SHARE = 26; {发生共享错误}
SE_ERR_ASSOCINCOMPLETE = 27; {文件名不完全或无效}
SE_ERR_DDETIMEOUT = 28; {超时}
SE_ERR_DDEFAIL = 29; {DDE 事务失败}
SE_ERR_DDEBUSY = 30; {正在处理其他 DDE 事务而不能完成该 DDE 事务}
SE_ERR_NOASSOC = 31; {没有相关联的应用程序}
//ShowCmd 参数可选值:
SW_HIDE = 0; {隐藏}
SW_SHOWNORMAL = 1; {用最近的大小和位置显示, 激活}
SW_NORMAL = 1; {同 SW_SHOWNORMAL}
SW_SHOWMINIMIZED = 2; {最小化, 激活}
SW_SHOWMAXIMIZED = 3; {最大化, 激活}
SW_MAXIMIZE = 3; {同 SW_SHOWMAXIMIZED}
SW_SHOWNOACTIVATE = 4; {用最近的大小和位置显示, 不激活}
SW_SHOW = 5; {同 SW_SHOWNORMAL}
SW_MINIMIZE = 6; {最小化, 不激活}
SW_SHOWMINNOACTIVE = 7; {同 SW_MINIMIZE}
SW_SHOWNA = 8; {同 SW_SHOWNOACTIVATE}
SW_RESTORE = 9; {同 SW_SHOWNORMAL}
SW_SHOWDEFAULT = 10; {同 SW_SHOWNORMAL}
SW_MAX = 10; {同 SW_SHOWNORMAL}
WinExec - 运行外部程序
//声明
WinExec(
lpCmdLine: LPCSTR; {文件名和参数; 如没指定路径会按以下顺序查找: 程序目录/当前目录/System32/Windows/PATH环境变量}
uCmdShow: UINT {启动选项}
): UINT;
//返回值:
大于 31 {调用成功}
等于 0 {内存不足}
ERROR_FILE_NOT_FOUND = 2; {文件名错误}
ERROR_PATH_NOT_FOUND = 3; {路径名错误}
ERROR_BAD_FORMAT = 11; {EXE 文件无效}
//uCmdShow 参数可选值:
SW_HIDE = 0; {隐藏, 并且任务栏也没有最小化图标}
SW_SHOWNORMAL = 1; {用最近的大小和位置显示, 激活}
SW_NORMAL = 1; {同 SW_SHOWNORMAL}
SW_SHOWMINIMIZED = 2; {最小化, 激活}
SW_SHOWMAXIMIZED = 3; {最大化, 激活}
SW_MAXIMIZE = 3; {同 SW_SHOWMAXIMIZED}
SW_SHOWNOACTIVATE = 4; {用最近的大小和位置显示, 不激活}
SW_SHOW = 5; {同 SW_SHOWNORMAL}
SW_MINIMIZE = 6; {最小化, 不激活}
SW_SHOWMINNOACTIVE = 7; {同 SW_MINIMIZE}
SW_SHOWNA = 8; {同 SW_SHOWNOACTIVATE}
SW_RESTORE = 9; {同 SW_SHOWNORMAL}
SW_SHOWDEFAULT = 10; {同 SW_SHOWNORMAL}
SW_MAX = 10; {同 SW_SHOWNORMAL}
//举例, 启动记事本:
procedure TForm1.Button1Click(Sender: TObject);
begin
WinExec('notepad.exe', SW_SHOWNORMAL);
end;