Главная страница
    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.057 c
15-1415658031
Германн
2014-11-11 01:20
2015.09.10
Вот так умирают бэкапные HD


2-1395057166
Вова
2014-03-17 15:52
2015.09.10
Работа функции CharInSet


15-1419162620
Zikurat
2014-12-21 14:50
2015.09.10
глюк MS SQL + ADO в асинхронном режиме


15-1418808674
zagayevskiy
2014-12-17 12:31
2015.09.10
Игра для Android


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