Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2015.09.10;
Скачать: [xml.tar.bz2];

Вниз

Автоматическое завершение дочернего процесса   Найти похожие ветки 

 
Дмитрий С ©   (2015-01-19 17:56) [0]

Запускаю в отдельном потоке некий процесс (не мой, переделывать его не имею возможности), который необходимо завершить вместе с завершением основной (моей) программы.
Если моя программа завершается штатно - то ничего сложного нет. Но если не штатно (пользователь убил через диспетчер задач) - так как быть тут?

В голову пока приходит только CreateRemoteThread+LoadLibrary+моя dll, которая будет следить за основным процессом.
Подскажите более изящные решения.


 
Rouse_ ©   (2015-01-19 18:12) [1]

http://msdn.microsoft.com/en-us/library/windows/desktop/ms684161(v=vs.85).aspx
плюс это: http://msdn.microsoft.com/en-us/library/windows/desktop/ms684147(v=vs.85).aspx см флаг JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE


 
Дмитрий С ©   (2015-01-19 18:49) [2]


> Rouse_ ©   (19.01.15 18:12) [1]

Благодарю! Буду разбираться.


 
alexdn ©   (2015-01-19 19:55) [3]

Удалено модератором
Примечание: Создание пустых сообщений


 
megavoid ©   (2015-01-20 00:01) [4]

волшебному слову watchdog много-много лет ;)


 
Дмитрий С ©   (2015-01-20 15:56) [5]

Спасибо еще раз. Второй вопрос на похожую тему.

Приложение, которое я запускаю - консольное. Программа штатно завершается, если нажать в консоли Ctrl+C (на Ctrl+Break - не завершается).
Запускать программу я буду с SW_HIDE с перенаправлением вывода в файл.

Вопрос: как штатно завершить программу?

P.S. GenerateConsoleCtrlEvent не работает ввиду ограничений наложенных на эту функцию.


 
Дмитрий С ©   (2015-01-20 16:00) [6]

Вот еще так себе вариант, но рабочий:

type
 TGenerateConsoleCtrlEvent = function (dwCtrlEvent: DWORD; dwProcessGroupId: DWORD): BOOL; stdcall;

function StopMe(RemoteGenerateConsoleCtrlEvent: TGenerateConsoleCtrlEvent): Bool; stdcall;
begin
 Result := RemoteGenerateConsoleCtrlEvent(0, 0);
end;



       StopProcPointer := VirtualAllocEx(PI.hProcess, nil, 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
       Win32Check(StopProcPointer <> nil);
       Win32Check(WriteProcessMemory(PI.hProcess, StopProcPointer, @StopMe, 1024, Dummy));
       StopThread := CreateRemoteThread(PI.hProcess, nil, 0, StopProcPointer, GetProcAddress(GetModuleHandle(kernel32), PChar("GenerateConsoleCtrlEvent")), 0, Dummy);
       Win32Check(StopThread <> 0);


 
Leonid Troyanovsky ©   (2015-01-21 12:19) [7]


> Дмитрий С ©   (20.01.15 16:00) [6]

> Вот еще так себе вариант, но рабочий:

Если ExitProcess - штатный, то посредством CreateRemoteThread
EP немного проще.

--
Regards, LVT.


 
Дмитрий С ©   (2015-01-21 13:45) [8]


> Если ExitProcess - штатный, то посредством CreateRemoteThread
> EP немного проще.

Проще, но тогда можно еще проще - вызвать TerminateProcess. В итоге процесс завершится "аварийно", а не штатно.

Учитывая, что времени на задачу уже нет, других способов для корректного завершения работы, кроме как вызвать GenerateConsoleCtrlEvent в контексте удаленного процесса я не нашел, а также учитывая, что во всеми любимой Delphi 7 не описаны Job функции итоговый  код получился примерно таким:


type
 PStopMeData = ^TStopMeData;
 TStopMeData = record
   ParentProcess: THandle;
   GenerateConsoleCtrlEvent: function (dwCtrlEvent: DWORD; dwProcessGroupId: DWORD): BOOL; stdcall;
   WaitForSingleObject: function (hHandle: THandle; dwMilliseconds: DWORD): DWORD; stdcall;
   GetCurrentProcess: function (): THandle; stdcall;
   TerminateProcess: function (hProcess: THandle; uExitCode: UINT): BOOL; stdcall;
 end;

function StopMe(Data: PStopMeData): Bool; stdcall;
begin
 Data^.WaitForSingleObject(Data^.ParentProcess, INFINITE);
 Data^.GenerateConsoleCtrlEvent(0, 0);
 Data^.WaitForSingleObject(Data^.GetCurrentProcess, 10000);
 Data^.TerminateProcess(Data^.GetCurrentProcess, 1);
 Result := True;
end;

...

     Win32Check(DuplicateHandle(GetCurrentProcess, GetCurrentProcess, PI.hProcess, @StopData.ParentProcess, PROCESS_ALL_ACCESS, True, 0));
     StopData.GenerateConsoleCtrlEvent := GetProcAddress(GetModuleHandle(kernel32), PChar("GenerateConsoleCtrlEvent"));
     StopData.WaitForSingleObject := GetProcAddress(GetModuleHandle(kernel32), PChar("WaitForSingleObject"));
     StopData.GetCurrentProcess := GetProcAddress(GetModuleHandle(kernel32), PChar("GetCurrentProcess"));
     StopData.TerminateProcess := GetProcAddress(GetModuleHandle(kernel32), PChar("TerminateProcess"));

     StopProcDataPointer := VirtualAllocEx(PI.hProcess, nil, SizeOf(StopData), MEM_COMMIT, PAGE_READWRITE);
     Win32Check(StopProcDataPointer <> nil);
     Win32Check(WriteProcessMemory(PI.hProcess, StopProcDataPointer, @StopData, SizeOf(StopData), Dummy));

     StopProcPointer := VirtualAllocEx(PI.hProcess, nil, 256, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
     Win32Check(StopProcPointer <> nil);
     Win32Check(WriteProcessMemory(PI.hProcess, StopProcPointer, @StopMe, 256, Dummy));
     StopThread := CreateRemoteThread(PI.hProcess, nil, 0, StopProcPointer, StopProcDataPointer, 0, Dummy);
     Win32Check(StopThread <> 0);

     WaitHandles[0] := PI.hProcess;
     WaitHandles[1] := FStopEvent.Handle;

     ContinueWait:
     case WaitForMultipleObjects(2, @WaitHandles, False, INFINITE) of
       WAIT_OBJECT_0, WAIT_ABANDONED_0: raise Exception.Create("Процесс X был неожиданно завершен.");
       WAIT_OBJECT_0 + 1, WAIT_ABANDONED_0 + 1: {Ничего, просто выходим};
       WAIT_TIMEOUT: goto ContinueWait;
       WAIT_FAILED: RaiseLastOsError;
     end;



Страницы: 1 вся ветка

Форум: "Прочее";
Текущий архив: 2015.09.10;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.045 c
2-1395390646
Роман
2014-03-21 12:30
2015.09.10
чтение из реестра


15-1420954292
alexdn
2015-01-11 08:31
2015.09.10
Ищу инвестора


15-1409765726
Павиа
2014-09-03 21:35
2015.09.10
Осторожно. Новый вид атак.


15-1420010989
brother
2014-12-31 10:29
2015.09.10
С наступающим!


11-1260465918
tippa
2009-12-10 20:25
2015.09.10
горячие клавиши в KOL





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский