2008-11-06 9 views
1

У меня есть служба Windows, написанная на Delphi, которая запускает несколько программ.Delphi - изящное закрытие созданного процесса в сервисе. (используя tprocess/createProcess)

Остановить службу, я хочу также закрыть эти программы. Когда служба была изначально написана, это сработало хорошо, но я думаю, что я обновил компонент tProcess и теперь - подчиненные программы не закрываются.

in tProcess - Вот код, который запускает новые процессы.

if CreateProcess(nil , PChar(FProcess.Command) , nil , nil , False , 
    NORMAL_PRIORITY_CLASS , nil , Directory , 
    StartupInfo , ProcessInfo) then 
    begin 
     if FProcess.Wait then 
     begin 
      WaitForSingleObject(ProcessInfo.hProcess , Infinite); 
      GetExitCodeProcess(ProcessInfo.hProcess , ExitCode); 
      if Assigned(FProcess.FOnFinished) then 
      FProcess.FOnFinished(FProcess , ExitCode); 
     end; 
     CloseHandle(ProcessInfo.hProcess); 
     CloseHandle(ProcessInfo.hThread); 
    end; 

Каждый из исполняемых файлов, вызываемых этим, представляет собой программы Windows GUI (с кнопкой закрытия вверху).

Когда я останавливаю службу, я также хочу остановить (не убивать) программы, которые я запускал с помощью процедуры createProcess.

Как вы это сделаете?

+0

начала не проблема, верно? Итак, что вы делаете или TProcess, чтобы закрыть программы? –

ответ

1

Вы хотите перечислить открытые окна, соответствующие вашему запущенному процессу, и сообщить этим окнам закрыть. Вот некоторые примеры кода для этого:

uses Windows; 

interface 

function MyTerminateAppEnum(hHwnd:HWND; dwData:LPARAM):Boolean; stdcall; 

implementation 

function MyTerminateAppEnum(hHwnd:HWND; dwData:LPARAM):Boolean; 
var 
    vID:DWORD; 
begin 
    GetWindowThreadProcessID(hHwnd, @vID); 
    if vID = dwData then 
    begin 
    PostMessage(hHwnd, WM_CLOSE, 0, 0); //tell window to close gracefully 
    Result := False; //can stop enumerating  
    end 
    else 
    begin 
    Result := TRUE; //keep enumerating until you find your id 
    end; 
end; 

Затем вы хотите использовать это в вашем коде, если вы хотите, чтобы закрыть начатые приложения:

Procedure TerminateMe(YourSavedProcessInfo:TProcessInformation); 
var 
    vExitCode:UINT; 
begin 
    GetExitCodeProcess(YourSavedProcessInfo.hProcess, vExitCode); 
    if (vExitCode = STILL_ACTIVE) then //launched app still running.. 
    begin 
    //tell it to close 
    EnumWindows(@MyTerminateAppEnum, YourSavedProcessInfo.dwProcessId); 

    if WaitForSingleObject(YourSavedProcessInfo.hProcess, TIMEOUT_VAL) <> WAIT_OBJECT_0 then 
    begin 
     if not TerminateProcess(YourSavedProcessInfo.hProcess, 0) then //didn't close, try to terminate 
     begin 
     //uh-oh Didn't close, didn't terminate.. 
     end; 
    end; 
    end; 
    CloseHandle(YourSavedProcessInfo.hProcess); 
    CloseHandle(YourSavedProcessInfo.hThread); 
end; 
4

Я бы использовал TJvCreateProcess компонент JVCL, который изящно обертывает любую связанную с процессом функциональность win32. Этот ответ исходит от Dont-touch-winapi-if-really-required отдела :-)

+0

Я думаю, что он уже использует такой класс, называемый TProcess –

1

Единственный общий способ остановить процесс - использовать TerminateProcess. Но это настолько далеко от изящного, что вы можете получить. Чтобы изящно закрыть процесс, вам нужно сообщить процессу, который вы хотите остановить, а затем надеяться, что он подчиняется. Но вообще-то этого не сделать.

Для программы GUI обычный способ сказать, что вы хотите, чтобы она перестала работать, - закрыть главное окно. Однако формального представления о «главном окне» нет. Программа может иметь ноль или более окон, и нет никакого способа узнать извне, какой из них вы должны закрыть, чтобы программа перестала работать.

Вы можете использовать EnumWindows для просмотра всех окон и выбора тех, которые относятся к вашему процессу. (Это были те, для которых GetWindowThreadProcessId дает тот же идентификатор процесса, который предоставил CreateProcess.)

Закрытие окна может быть недостаточным. Программа может отображать диалоговое окно (запрос на подтверждение или запрос на сохранение изменений и т. Д.). Вам нужно заранее знать, как отклонить это диалоговое окно.

Программы, не относящиеся к GUI, могут иметь схожие проблемы. Это может быть достаточно, чтобы имитировать Ctrl + C нажатие клавиши. Тем не менее, это может похвастаться и обрабатывать это нажатие. Он может иметь систему меню, которая ожидает, что вы наберете «Q», чтобы выйти из программы.

Короче говоря, вы не можете изящно закрыть программу, если не знаете заранее, как эта программа ожидает закрытия.