Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как дождаться запуска приложения ? [D7, WinXP]


BFG9k ©   (2007-05-23 15:33:00) 

Как запустить программу и дождаться ее запуска ? Обращаю внимание: не завершения работы, а именно запуска, то есть когда она до конца загрузится.


Riply   (2007-05-25 07:40:00) [1]

>[12] Leonid Troyanovsky © (24.05.07 18:10)
> Riply © недавно с этим воевала и могла б про это рассказать.
> Но, видимо, просматривает она только "Начинающих".
Заглядываю и сюда. Вот объявилась :)
Что рассказыать не знаю, т.к. в http://www.delphimaster.ru/cgi-bin/forum.pl?n=18&id=1178820436
весь процесс попытки поймать "момент окончания инициализации процесса" разобран по косточкам.
Можно только более подробно расписать схему поимки, предложенную Leonid Troyanovsky,
и поделиться результатами тестирования.

Подготавливаем APCProc, примерно такого вида:
procedure APCProc(dwParam: Dword); stdcall;
var
OldState: Boolean;
begin
with PInjectInfo(dwParam) do
 begin
  ...............................
  LastStatus := _NtSetEvent(hReadyEvent, @OldState);
  if LastStatus STATUS_INVALID_HANDLE then
   begin
    LastStatus := _NtClose(hReadyEvent);
    hReadyEvent := 0;
   end;
 end;
end;
"Требования к коду APCProc такие же, как в случае с CRT."

Создаем процесс:
CreateProcess(..., CREATE_SUSPENDED, ..., Proc_Info);
Создаем hEvent, сигнал котрого будем ожидать:
hEvent := CreateEvent(nil, True, False, nil);
"Дупликатим" его :)
DuplicateHandle(GetCurrentProcess, hEvent, Proc_Info.hProcess, @hDupEvent, 0, False, DUPLICATE_SAME_ACCESS)
Пишем в адресное пространство жертвы структуру TInjectInfo, содержащую
1. Адреса функций, которые будем использовать в APCProc
2. hDupEvent - дубликат нашего hEvent
3. Всякие полезные мелочи :)
4. и сам код нашей APCProc
Proc_WriteMemory(Proc_Info.hProcess, pInjectInfo, TmpSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE, pRemoteData)
У меня она выглядит, примерно так:
type
PInjectInfoBase = ^TInjectInfoBase;
TInjectInfoBase = packed record
 ......
 NtFuntionsTable: TNtFunctTable;
 hReadyEvent: THandle;
 LastStatus: NTSTATUS;
 RetResult: DWord;
 ......
 function pInjectTreadCode: Pointer;
end;

function TInjectInfoBase.pInjectTreadCode: Pointer;
begin
Result := Pointer(DWord(@Self) + SizeOf(TInjectInfoBase));
end;

Где TNtFunctTable - стуктура, содержащая адреса Nt или kernel32 - функций.
TNtFunctTable = packed record
_RtlGetLastNtStatus: function: NTSTATUS; stdcall;
_NtSetEvent: function(EventHandle: THANDLE; OldState: PBOOLEAN): NTSTATUS; stdcall;
................................... и т. д.
Создаем нить в теле жертвы:
QueueUserAPC(PInjectInfoBase(pRemoteData).pInjectTreadCode, Proc_Info.hThread, DWord(pRemoteData))
Будим целевой процесс:
ResumeThread(Proc_Info.hThread)
И ждем срабатывания нашего hEvent - а.
WaitArr := Make_Int64(Proc_Info.hProcess, hEvent);
WaitResult := WaitForMultipleObjects(2, @WaitArr, False, TimeOut);
Вот, вроде, и все.
У меня все работает "на ура". Тестировала на самых разных(специально для этого созданных) процессах.
Как и говорил Leonid Troyanovsky:
"APCProc срабатывает _непосредственно_после_инициализации процесса, но _до_выполнения main & etc" :)
>[0] BFG9k © (23.05.07 15:33)
Будут вопросы - задавай.


Leonid Troyanovsky   (2007-05-24 18:10:00) [2]


> clickmaker ©   (24.05.07 11:31) [9]

> Для консольных и без цикла выборки сообщений функция вообще
> смысла не имеет.

Для некоторых консольных - имеет.

> Формально, если WinMain / main() стартовала, это значит,
>  что приложение уже загрузилось

Во-ще-то, в [4] есть верная ссылочка, бо уважаемая Riply ©
недавно с этим воевала и могла б про это рассказать.
Но, видимо, просматривает она только "Начинающих".

--
Regards, LVT.


Leonid Troyanovsky   (2007-05-24 18:04:00) [3]


> antonn (work)   (23.05.07 20:50) [5]

> семафор и искать его переодически в мониторящей

Удобней взять событие (наследуемое) и пускать
дочерний процесс с наследованием хендлов.
Значение хендла можно передать, например в комстроке.
Тогда дочернему процессу достаточно сделать SetEvent
в числе первого выполняемого кода.

--
Regards, LVT.


Юрий Зотов   (2007-05-24 13:34:00) [4]

> SpellCaster   (24.05.07 11:25) [8]

См. описание функции в справке Win32 SDK или [9].


clickmaker   (2007-05-24 11:31:00) [5]

да может и не помочь. Это всего лишь означает, что приложение запустило цикл обработки сообщений и в очереди нет необработанных, т.е. оно готово к приему информации извне.
Для консольных и без цикла выборки сообщений функция вообще смысла не имеет.
Так что уточнения требует момент "когда она до конца загрузится" - что под этим понимать?
Формально, если WinMain / main() стартовала, это значит, что приложение ужезагрузилось


SpellCaster   (2007-05-24 11:25:00) [6]

> [6] Юрий Зотов ©   (23.05.07 21:19)


> WaitForInputIdle может и не помочь

А в каких случаях это может случиться?


Сергей М.   (2007-05-24 08:20:00) [7]


> BFG9k ©   (23.05.07 16:27) [3]


Куда ж без нее)


Юрий Зотов   (2007-05-23 21:19:00) [8]

> BFG9k ©   (23.05.07 16:27) [3]

А зря упрекаете. WaitForInputIdle может и не помочь, так что Сергей М. вполне может оказаться не менее правым, чем clickmaker.


antonn (work)   (2007-05-23 20:50:00) [9]

если запускаемая программа своя и мониторящая своя, то в запускаемой в "момент окончательной загрузки" можно создавать семафор и искать его переодически в мониторящей


Kedge   (2007-05-23 20:32:00) [10]

>[0] BFG9k ©   (23.05.07 15:33)
>то есть когда она до конца загрузится.
http://www.delphimaster.ru/cgi-bin/forum.pl?n=18&id=1178820436


BFG9k   (2007-05-23 16:27:00) [11]

clickmaker, спасибо.

Сергей М., сколько уверенности ..... :)


Сергей М.   (2007-05-23 15:46:00) [12]


> BFG9k ©   (23.05.07 15:33)


> Как запустить программу и дождаться..когда она до конца загрузится


Никак.
WinAPI не предоставляет польз.интерфейса для мониторинга выполнения именно этогоэтапа.


clickmaker   (2007-05-23 15:36:00) [13]

WaitForInputIdle()?


Наверх

Титульная страница Поиск, карта сайта Написать письмо