Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.145.175.243] |
|
Сообщ.
#1
,
|
|
|
У окна которое я ищу постоянно меняется название, можно конечно поискать по той части названия которая неизменна. Но а если такой части нет, ведь если по окну можно найти процесс то наверное и обратно тоже можно... Хотя процесс может иметь несколько окон, но в любом случае среди них найти будет проще.
|
Сообщ.
#2
,
|
|
|
Daemon, можно по имени класса искать.
|
Сообщ.
#3
,
|
|
|
Krid, можно, знать бы ещё по какому
|
Сообщ.
#4
,
|
|
|
ээээ... а какие вообще есть критерии, по которым можно отличить именно это окно от других? Имя проги (exe'шник)? Тогда чем оно отличается от остальных окон процесса?
|
Сообщ.
#5
,
|
|
|
Цитата Daemon @ можно, знать бы ещё по какому Ставишь курсор над этим окном и выполняешь такой код: procedure TForm2.Timer1Timer(Sender: TObject); var H: HWND; P: TPoint; Buff: array [0..255] of Char; begin GetCursorPos(P); H := WindowFromPoint(P); GetClassName(H, Buff, SizeOf(Buff)); Memo1.Lines.Add(String(Buff)); end; |
Сообщ.
#6
,
|
|
|
Rouse_, это не самый удобный и немного напрягающий метод. Мне нужнна полная автоматизация.
Krid, есть exe-шник и знание того что окно 'главное'. На самом деле если без заморочек нельзя то и ... с ним. И ещё вопрос в продолжение темы. Предположим окно я нашёл, а как можно отлавливать изменения происходящие с ним (изменение размера например или потерю фокуса)? И ещё, можно ли определить осталось ли окно видимым после потери фокуса, точнее даже не всё окно а его определённая часть? Фактически надо получить окно липучку |
Сообщ.
#7
,
|
|
|
Цитата Daemon @ это не самый удобный и немного напрягающий метод Это самый простой метод помогающий узнать класс окна. Он же у тебя не будет изменяться. Соответственно, при помощи него определи класс окна (как я показал), а потом как и сказал Krid, ищешь окно по имени класса и делай с ним все что тебе необходимо. Цитата Daemon @ а как можно отлавливать изменения происходящие с ним (изменение размера например или потерю фокуса)? Ну тут уже придется внедрять свой код в адресное пространство процесса в котором отображается это окно (к примеру хуком - самое универсальное) и там перехватывать все события адресованые этому окну. |
Сообщ.
#8
,
|
|
|
Цитата Rouse_ @ Это самый простой метод помогающий узнать класс окна. Он же у тебя не будет изменяться. Соответственно, при помощи него определи класс окна (как я показал), а потом как и сказал Krid, ищешь окно по имени класса и делай с ним все что тебе необходимо. Хм... да действительно, грамотно. Цитата Rouse_ @ Ну тут уже придется внедрять свой код в адресное пространство процесса в котором отображается это окно (к примеру хуком - самое универсальное) и там перехватывать все события адресованые этому окну. УУУ, а где нить пример нарыть можно...? А то я даже толком не понимаю чего искать надо |
Сообщ.
#9
,
|
|
|
Daemon, послушай Rouse_'а. Тебе нужно только 1 раз узнать имя класса окна. Дальше ты его зашьешь в прогу (как и имя exe'шника) и все.
Ну, если очень хочется поизвращаться, можно примерно так: const exeName = 'MYPROG.EXE'; var fWnd:hwnd; function GetModuleFileNameExW(hProcess:THandle; hModule:HMODULE; lpFilename:PWideChar; nSize:DWORD):DWORD; stdcall; external 'PSAPI.DLL' function WindowGetEXE(wnd:HWND):string; // для Win2K/XP. В Win9x нужно юзать GetWindowModuleFileName var wt:array[0..MAX_PATH-1] of WChar; prc:THandle; prcID:cardinal; begin result:=''; if GetWindowThreadProcessID(wnd,prcID)<>0 then begin prc:=OpenProcess(PROCESS_ALL_ACCESS,false,prcID); if prc<>0 then try if GetModuleFileNameExW(prc,0,wt,MAX_PATH*2)<>0 then result:=wt finally CloseHandle(prc) end end end; function EnumWindowsProc(wnd:HWND; lParam: LPARAM):BOOL; stdcall; begin result:=true; if IsWindowVisible(wnd) and (GetParent(wnd)=0) and (wnd<>Application.Handle) and (wnd<>Form1.Handle) // проверка, что окно не твое собственное. and (UpperCase(ExtractFileName(WindowGetEXE(wnd)))=exeName) then begin fWnd:=wnd; result:=false end end; procedure TForm1.Button1Click(Sender: TObject); begin fWnd:=0; EnumWindows(@EnumWindowsProc,0); if fWnd=0 then ShowMessage('Not found') else ShowMessage('Found window '+IntToStr(fWnd)) end; Но этот способ, имхо не гарантирует, что будет найдено именно то окно. Лучше всего узнать имя класса. Добавлено с небольшим опозданием |
Сообщ.
#10
,
|
|
|
Цитата Daemon @ УУУ, а где нить пример нарыть можно...? Посмотрю, гдето у меня дома валялся пример с определением процессов с таймером. Там примерно такойже принцип использовался... |
Сообщ.
#11
,
|
|
|
Цитата Daemon @ А то я даже толком не понимаю чего искать надо DLL injecting и subclassing |
Сообщ.
#12
,
|
|
|
Цитата Krid @ Лучше всего узнать имя класса. С именем класса тоже не всё гладко, дело в том что на данный момент с текущей версией программы всё работает, а какие имена были у старых версий и что будет с новыми неизвестно. Поэтому я и хотел привязаться к имени exe-шника ибо он всегда тот же. Добавлено Цитата Rouse_ @ Посмотрю, гдето у меня дома валялся пример с определением процессов с таймером. Там примерно такойже принцип использовался... Жду и надеюсь |
Сообщ.
#13
,
|
|
|
Daemon, еще можешь попробовать например ToolHelp. Получаешь ID процесса и внедряешься в него CreateRemoteThread'ом. Но это только для Win2K+. Можешь мой код (или подобный какой-нить) юзать и внедряться с помощью ловушек (и Win9x и Win2K+).
Ну а после внедрения - subclassing (замена чужой оконной процедуры на свою, перехват сообщений). Добавлено Да, а про внедрение Рихтера почитай (если не читал еще). 22-ю главу. |
Сообщ.
#14
,
|
|
|
Вот тебе пример внедрения:
function SetDebugPriv: Boolean; var Token: THandle; tkp: TTokenPrivileges; begin Result := false; if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token) then begin if LookupPrivilegeValue(nil, PChar('SeDebugPrivilege'), tkp.Privileges[0].Luid) then begin tkp.PrivilegeCount := 1; tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; Result := AdjustTokenPrivileges(Token, false, tkp, 0, PTokenPrivileges(nil)^, PDWord(nil)^); end; end; end; function TfrmMain.InjectLib(const ProcessID: DWORD): Boolean; var Process: HWND; ThreadRtn: FARPROC; DllPath: String; RemoteDll: Pointer; BytesWriten: DWORD; Thread: DWORD; ThreadId: DWORD; ExitCode: DWORD; begin // Устанавливаем отладочные привилегии для нашего процесса Result := SetDebugPriv; if not Result then Exit; Process := 0; Thread := 0; try // Открываем процесс Process := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_WRITE, True, ProcessID); if Process = 0 then Exit; // Выделяем в нем память под строку DllPath := ExtractFilePath(ParamStr(0)) + 'hooklib.dll'; RemoteDll := VirtualAllocEx(Process, nil, Length(DllPath), MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE); if RemoteDll = nil then Exit; // Пишем путь к длл в его адресное пространство if not WriteProcessMemory(Process, RemoteDll, PChar(DllPath), Length(DllPath), BytesWriten) then Exit; if BytesWriten <> DWORD(Length(DllPath)) then Exit; // Получаем адрес функции в Kernel32.dll ThreadRtn := GetProcAddress(GetModuleHandle('Kernel32.dll'), 'LoadLibraryA'); if ThreadRtn = nil then Exit; // Запускаем удаленный поток Thread := CreateRemoteThread(Process, nil, 0, ThreadRtn, RemoteDll, 0, ThreadId); if Thread = 0 then Exit; // Ждем пока удаленный поток отработает... if (WaitForSingleObject(Thread, INFINITE) = WAIT_OBJECT_0) then if GetExitCodeThread(Thread, ExitCode) then Result := ExitCode = 0; finally // Удаленный поток свою задачу выполнил и загрузил нашу библиотеку, // можно освобождать занятую память... if RemoteDll <> nil then VirtualFreeEx(Process, @RemoteDll, 0, MEM_RELEASE); if Thread <> 0 then CloseHandle(Thread); if Process <> 0 then CloseHandle(Process); end; end; Пример использования: if InjectLib(GetCurrentProcessID{или PID открытого процесса}) then lbStatus.Items.Add('Library injected succes.') else lbStatus.Items.Add('Library injected fail.') Соответственно, пиши свою библиотеку, которая при загрузке делает сабклассинг, потом ищи нужное окно, получай PID процесса GetWindowThreadProcessId, и выполняй данный код... Вот так вот в кратце... |
Сообщ.
#15
,
|
|
|
Хехе
Думаю завтра у меня появится много вопросов... |