WinNT でウィンドウハンドルから実行アプリ名を知る
|
WinNT では、ToolHelp32 が使えないので、Win95 で良く知られた方法(ToolHelp32)は使えません。
http://www.microsoft.com/japan/support/kb/articles/J041/6/32.htm
に、Win95/NT 両方で使える方法が C 言語で書かれてます。
ここでは、PSAPIを使っています。
上記の部分的丸写しですが。
uses PsApi;
type
TEnumProcs = function(ID: DWord; Str: PChar; LP: LParam):bool; stdcall;
procedure EnumProcessesNT(lpEnumFunc: TEnumProcs; lParam: longint);
var
// 関数ポインタ
EnumProcesses: TEnumProcesses;
EnumProcessModules: TEnumProcessModules;
GetModuleFileNameEx: TGetModuleFileNameEx;
// 変数
hLib: THandle;
Process: THandle;
hMod: DWORD;
PIDs: array[0..2047] of DWORD; // 動的配列ポインタの扱いを簡素化(^^;
Size, Size2, Index: DWORD;
ProcessName: array[0..MAX_PATH] of char;
begin
hMod := 0;
// PSAPI.DLL のロード
hLib := LoadLibraryA('PSAPI.DLL');
if hLib = 0 then
raise Exception.Create('PSAPI.DLL がロードできません。');
// API のアドレス取得(以下の3個を使う)
EnumProcesses := TEnumProcesses(GetProcAddress(hLib, 'EnumProcesses'));
EnumProcessModules := TEnumProcessModules(GetProcAddress(hLib, 'EnumProcessModules'));
GetModuleFileNameEx := TGetModuleFileNameEx(GetProcAddress(hLib, 'GetModuleFileNameExA'));
// ロードのチェック
if (not Assigned(EnumProcesses))
or(not Assigned(EnumProcessModules))
or(not Assigned(GetModuleFileNameEx)) then
begin
FreeLibrary(hLib);
raise Exception.Create('API のアドレスを取得できません。');
end;
// プロセスの数は2048まで
Size2 := 2048 * SizeOf(DWORD);
if not EnumProcesses(@PIDs, Size2, Size) then
begin
FreeLibrary(hLib);
raise Exception.Create(SysErrorMessage(GetLastError));
end;
if Size >= Size2 then
begin
FreeLibrary(hLib);
raise Exception.Create('2048 個以上のプロセスがあるみたいです。');
end;
Size := Size div SizeOf(DWORD);
for Index := 0 to Size - 1 do
begin
// プロセスを読み出す
Process := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
False, PIDs[Index]);
if Process <> 0 then
begin
// プロセスのモジュールをチェック
if EnumProcessModules(Process, PDWORD(hMod), SizeOf(hMod), Size2) then
begin
// ファイル名を取得
if GetModuleFileNameEx(Process, hMod, ProcessName, SizeOf(ProcessName)) = 0 then
begin
ProcessName:='';
end;
end;
CloseHandle(Process);
end
else
ProcessName:='';
// コールバック関数を呼び出し
if not lpEnumFunc(PIDs[Index], ProcessName, lParam) then
else Break;
end;
// 解放
FreeLibrary(hLib);
end;
// 使用例
function CallBackTest(ID: DWord; Str: PChar; LP: LParam):bool;stdcall;
begin
TListBox(LP).Items.Addobject(Str,Pointer(ID));
Result := True;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ListBox1.Items.Clear;
EnumProcessesNT(@CallBackTest,Longint(ListBox1));
// リストボックスに列挙する
end;
|
|