Главная страница
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.49 MB
Время: 0.12 c
4-1272049250
@!!ex
2010-04-23 23:00
2015.09.10
Как из service удалить куки для всех пользователей?


15-1419680039
alexdn
2014-12-27 14:33
2015.09.10
Папки в Skype


6-1276442822
Иван
2010-06-13 19:27
2015.09.10
Проблема при передачи tcpserver tcpclient


2-1393570213
Михаил
2014-02-28 10:50
2015.09.10
вставка текста в MS Word через OleContainer


15-1422221404
Юрий
2015-01-26 00:30
2015.09.10
С днем рождения ! 26 января 2015 понедельник