Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2015.09.10;
Скачать: CL | DM;

Вниз

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

 
Дмитрий С ©   (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;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.044 c
1-1330588997
Deltas
2012-03-01 12:03
2015.09.10
Автоматическое подключение модулей в секции uses


4-1271754311
QAZ
2010-04-20 13:05
2015.09.10
FindFirstFileW и FindNextFileW


15-1413837002
Юрий
2014-10-21 00:30
2015.09.10
С днем рождения ! 21 октября 2014 вторник


15-1411849802
Юрий
2014-09-28 00:30
2015.09.10
С днем рождения ! 28 сентября 2014 воскресенье


15-1421265883
sysdmg4
2015-01-14 23:04
2015.09.10
Система тестирования ПО на основе виртуальных машин - нужен совет





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский