Доброго времи суток форумчане! Вопрос следующий: как узнать имя процеса по hwnd. Просматрел многие форумы и не нашёл ответа, только узнал как получить имя класса, заголовок окна, PID процесса. Хотелось бы узнать как получить имя процесса как в диспечере задач(имя образа).
20.02.08 13:04: Перенесено модератором из 'Delphi & Builder' — Hacker_Delphi
Здравствуйте, Аноним, Вы писали:
А>Доброго времи суток форумчане! Вопрос следующий: как узнать имя процеса по hwnd. Просматрел многие форумы и не нашёл ответа, только узнал как получить имя класса, заголовок окна, PID процесса. Хотелось бы узнать как получить имя процесса как в диспечере задач(имя образа).
Во-первых, нет такого понятия, как "имя процесса". То, что показывает TaskMgr — это имя исполняемого модуля. Получить его можно, перечисляя все процессы в системе (NtQuerySystemInformation(), Process32First()/Process32Next() — выбирайте по вкусу), в этом списке будет и интересующий вас процесс
Re[2]: Узнать имя процеса по hwnd
От:
Аноним
Дата:
19.02.08 11:06
Оценка:
Здравствуйте, _Ursus_, Вы писали:
_U_>Во-первых, нет такого понятия, как "имя процесса". То, что показывает TaskMgr — это имя исполняемого модуля. Получить его можно, перечисляя все процессы в системе (NtQuerySystemInformation(), Process32First()/Process32Next() — выбирайте по вкусу), в этом списке будет и интересующий вас процесс
Точнее поставлю вопрос. Как по HWND, не просто перечисляя все процессы в системе, а имея конкретный HWND окна узнать имя исполняющего модуля?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, _Ursus_, Вы писали:
_U_>>Во-первых, нет такого понятия, как "имя процесса". То, что показывает TaskMgr — это имя исполняемого модуля. Получить его можно, перечисляя все процессы в системе (NtQuerySystemInformation(), Process32First()/Process32Next() — выбирайте по вкусу), в этом списке будет и интересующий вас процесс
А>Точнее поставлю вопрос. Как по HWND, не просто перечисляя все процессы в системе, а имея конкретный HWND окна узнать имя исполняющего модуля?
Здравствуйте, Аноним, Вы писали: А>Точнее поставлю вопрос. Как по HWND, не просто перечисляя все процессы в системе, а имея конкретный HWND окна узнать имя исполняющего модуля?
Никак, только перебором.
Просто Process ID получить можно: GetWindowThreadProcessId(HWND, @PID);
Но для того чтобы получить имя процесса придется использовать перебор, либо загонять PID и имя процесса (образа в Vista) в массив и идти по индексам, хотя это, на мой взгляд, муторно в Delphi. Плюс снятие снапшота и перебор, если реализовать его правильно, будет затрачивать незначительное процессорное время.
Здравствуйте, Rook, Вы писали:
R>Никак, только перебором.
R>Просто Process ID получить можно: GetWindowThreadProcessId(HWND, @PID);
PID по hwnd я могу получить, спасибо. Вот встаёт тогда вопрос как можно получить по PID(если по HWND муторно) получить имя исполняемого модуля?
Пишу на Билдере. Вот такой у меня код получился.
//узнать ПИД процесса
unsigned long* pPid; //LPDWORD
void *hg; //HGLOBAL
hg = GlobalAlloc(GMEM_SHARE,sizeof(unsigned long));
pPid = (unsigned long *)GlobalLock(hg);
GetWindowThreadProcessId(win,pPid);
Но как теперь из этого всего получить имя запускаемого модуля(как в диспетчере задач имя образа). Подскажите кто сможет с примером, а то уже третий день не могу найти нигде. Извините за тупость, но может кто подскажет с примером на Builder.
Заранее благодарен.
Здравствуйте, Lexus_, Вы писали:
L_>Но как теперь из этого всего получить имя запускаемого модуля(как в диспетчере задач имя образа). Подскажите кто сможет с примером, а то уже третий день не могу найти нигде. Извините за тупость, но может кто подскажет с примером на Builder.
Уже 20 раз за последнее время пробегало в форуме WinAPI да и тебе уже говорили:
Конкретный ответ, таких способов нет
GetWindowThreadProcessId — взяли процес — уже сделано...
CreateToolhelp32Snapshot — вызвали с TH32CS_SNAPPROCESS
Process32First — получили первый процес
Process32Next — следующий и тд
Дальше разжевывать или проявите смекалку?
... << RSDN@Home 1.2.0 alpha rev. 790>>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Здравствуйте, Lexus_, Вы писали: L_>Но как теперь из этого всего получить имя запускаемого модуля(как в диспетчере задач имя образа). Подскажите кто сможет с примером, а то уже третий день не могу найти нигде. Извините за тупость, но может кто подскажет с примером на Builder. L_>Заранее благодарен.
Под билдер не могу, могу под дельфи. Но переписать, насколько я помню, не трудно и билдер умеет работать с паскалевскими файлами.
Я использую вот это, но не рекомендую использовать для циклических операций будет съедать много процессорного времени. Ружна оптимизация снятия снапшотов, она самая ресурсоёмкая получилась:
function RunningProcessesList(const List: TStrings; FullPath: Boolean): Boolean;
function ProcessFileName(PID: DWORD): string;
var
Handle: THandle;
begin
Result := '';
Handle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
if Handle <> 0 then
try
SetLength(Result, MAX_PATH);
if FullPath then
begin
if GetModuleFileNameEx(Handle, 0, PChar(Result), MAX_PATH) > 0 then
SetLength(Result, StrLen(PChar(Result)))
else
Result := '';
end
else
begin
if GetModuleBaseNameA(Handle, 0, PChar(Result), MAX_PATH) > 0 then
SetLength(Result, StrLen(PChar(Result)))
else
Result := '';
end;
finally
CloseHandle(Handle);
end;
end;
function BuildListTH: Boolean;
var
SnapProcHandle: THandle;
ProcEntry: TProcessEntry32;
NextProc: Boolean;
FileName: string;
begin
SnapProcHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
Result := (SnapProcHandle <> INVALID_HANDLE_VALUE);
if Result then
try
ProcEntry.dwSize := SizeOf(ProcEntry);
NextProc := Process32First(SnapProcHandle, ProcEntry);
while NextProc do
begin
if ProcEntry.th32ProcessID = 0 then
begin
FileName := RsSystemIdleProcess;
end
else
begin
if IsWin2k or IsWinXP then
begin
FileName := ProcessFileName(ProcEntry.th32ProcessID);
if FileName = ''then
FileName := ProcEntry.szExeFile;
end
else
begin
FileName := ProcEntry.szExeFile;
if not FullPath then
FileName := ExtractFileName(FileName);
end;
end;
List.AddObject(FileName, Pointer(ProcEntry.th32ProcessID));
NextProc := Process32Next(SnapProcHandle, ProcEntry);
end;
finally
CloseHandle(SnapProcHandle);
end;
end;
function BuildListPS: Boolean;
var
PIDs: array [0..1024] of DWORD;
Needed: DWORD;
I: Integer;
FileName: string;
begin
Result := EnumProcesses(@PIDs, SizeOf(PIDs), Needed);
if Result then
begin
for I := 0 to (Needed div SizeOf(DWORD)) - 1 do
begin
case PIDs[I] of
0:
FileName := RsSystemIdleProcess;
2:
if IsWinNT4 then
FileName := RsSystemProcess
else
FileName := ProcessFileName(PIDs[I]);
8:
if IsWin2k or IsWinXP then
FileName := RsSystemProcess
else
FileName := ProcessFileName(PIDs[I]);
else
FileName := ProcessFileName(PIDs[I]);
end;
if FileName <> ''then
List.AddObject(FileName, Pointer(PIDs[I]));
end;
end;
end;
begin
if IsWin3X or IsWinNT4 then
Result := BuildListPS
else
Result := BuildListTH;
end;
function GetProcessNameFromWnd(Wnd: HWND): string;
var
List: TStringList;
PID: DWORD;
I: Integer;
begin
Result := '';
if IsWindow(Wnd) then
begin
PID := INVALID_HANDLE_VALUE;
GetWindowThreadProcessId(Wnd, @PID);
List := TStringList.Create;
try
if RunningProcessesList(List, True) then
begin
I := List.IndexOfObject(Pointer(PID));
if I > -1 then
Result := List[I];
end;
finally
List.Free;
end;
end;
end;
вызов через filename := GetProcessNameFromWnd(window_handle);
R>Под билдер не могу, могу под дельфи. Но переписать, насколько я помню, не трудно и билдер умеет работать с паскалевскими файлами.
Ну вот, это почти то, что надо. Вот опять проблемка. Я так уже пытался сделать, но получается какае-то ерунда.
Вот мой код
hg = GlobalAlloc(GMEM_SHARE,sizeof(unsigned long));
pPid = (unsigned long *)GlobalLock(hg);
//узнаю PID текущего окна в виндовс
GetWindowThreadProcessId(hWnd,pPid);
DWORD PID;
HANDLE MyHandle;
//беру указатель процесса на данный ПИД
MyHandle = OpenProcess(PROCESS_QUERY_INFORMATION || PROCESS_VM_READ, false, PID);
char s[MAX_PATH];
//пытаюсь прочитать по указателю с помошью вот этой функции имя,
//но получается ерунда. Насколько я понял, то дело в том,
//что эта функция получает указатель на модуль(первый параметр), а я ей передаю указатель но процесс
// а вот функция GetModuleFileNameExА(то что надо, насколько я понял надо). Для неё надо подключить библиотеку Psapi.h, но после подключения этой библиотеки компилятор ругается на
[Linker Error] Unresolved external 'GetModuleFileNameExA' referenced from D:\ПАПКА\ASDF.OBJ
GetModuleFileName(MyHandle, s, MAX_PATH);
В переменной s получается набор беспорядочный знаков.
Может кто подскажет как использовать данную функцию GetModuleFileNameExA (msdn посмотрел, но ничего там не нашёл).
Rook, Вы писали свой код, а вы подключали какие либо библиотеки для использования функциями GetModuleFileNameEx или GetModuleBaseNameA?
Здравствуйте, Rook, Вы писали:
R>Под билдер не могу, могу под дельфи. Но переписать, насколько я помню, не трудно и билдер умеет работать с паскалевскими файлами.
R>Я использую вот это, но не рекомендую использовать для циклических операций будет съедать много процессорного времени. Ружна оптимизация снятия снапшотов, она самая ресурсоёмкая получилась:
Спасибо Вас за помощь. Наконец-то разобрался
Вот привожу мой код на С++(писал на Билдере), может кому пригодится:
AnsiString GetProcessName(HWND hWnd)
{
//PID -процесса
unsigned long * PID;
//указатель на процесс
HANDLE hProc;
//имя процесса
char ProcessName[80];
//указатель на модуль
HMODULE ahMod [10];
DWORD dwNeeded;
void *hg; //HGLOBAL
hg = GlobalAlloc(GMEM_SHARE,sizeof(unsigned long));
PID = (unsigned long *)GlobalLock(hg);
//получить ПИД процесса
GetWindowThreadProcessId(hWnd,PID);
//по ПИД получить указатель на процесс
hProc = OpenProcess (PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
FALSE,
*PID); // PID должен быть обьявлен как DWORD
if (hProc)
{
if (EnumProcessModules (hProc,
ahMod,
sizeof(ahMod),
&dwNeeded))
{
if (GetModuleBaseName (hProc,
ahMod[0],
ProcessName,
sizeof(ProcessName)))
{
return ProcessName;
}
else
{
return "";
}
}
CloseHandle (hProc);
}
}
Пример вызовы(узнать имя процесса активного окна)
GetProcessName(GetForegroundWindow()));
Возвращает переменную с именем типа AnsiString