Текущий архив: 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