|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
Как отловить закрытие запущенного приложения
Запускаю из своего приложения стороннюю программу, с помощью ShellExecute как можно отловить закрытие приложения, чтобы продолжить выполнение кода.
Код:
procedure TForm1.ReadButClick(Sender: TObject); var s: TStringList; begin if ((AddrEdit1.Text = '') or (AddrEdit2.Text = '') or (AddrEdit3.Text = '')) then begin ShowMessage(' Вы не заполнили поля' + #13 + 'адресов концентраторов'); Exit; end; if PhoneEdit.Text = '+7' then begin ShowMessage('Вы не ввели номер телефона'); Exit; end; s := TStringList.Create; s.LoadFromFile('Config.dat'); s.Text:=StringReplace(s.Text,'Phone',PhoneEdit.Text,[rfreplaceall]); s.Text:=StringReplace(s.Text,'Addr1',AddrEdit1.Text,[rfreplaceall]); s.Text:=StringReplace(s.Text,'Addr2',AddrEdit2.Text,[rfreplaceall]); s.Text:=StringReplace(s.Text,'Addr3',AddrEdit3.Text,[rfreplaceall]); s.SaveToFile('Root.dat'); FreeAndNil(s); ShellExecute(Handle, 'open', 'BQuark.Rev.3.3.exe', 'Root.dat', nil, SW_SHOWNORMAL); //Здесь должен идти код дальше после закрытия BQuark. |
#2
|
|||
|
|||
Из ShellExecute - никак.
Тебе надо использовать CreateProcess. В этом случае ты получишь некоторый Handle, который можно проверять на валидность. Как только он освободится - значит приложение закрылось. |
#3
|
||||
|
||||
С одного старого проекта вырезка:
Код:
PThreadParams = ^TThreadParams; TThreadParams = record // параметры, передаваемые в поток Wnd: HWND; // окно, получающее сообщения из потока Num: TChapterNumber; // номер запускаемой лекции end; function LectureThreadProc(p: Pointer): DWORD; stdcall; // функция потока var Buffer: array[0..1023] of Char; tmp_filename, app_filename: string; stream: TResourceStream; lpHandles: array[0..1] of THandle; fe_res: Integer; SInfo: TStartupInfo; PInfo: TProcessInformation; begin PostMessage(PThreadParams(p)^.Wnd, WM_LECTURE_THREAD, wLECTURE_RUN, 0); // отправляем окну сообщение о старте потока tmp_filename := Format(LECTURE_FORMAT_FILE, [TMPpath, PThreadParams(p)^.Num]); // формируем имя временного файла stream := TResourceStream.Create(HInstance, Format(LECTURE_FORMAT_RESOURCE, [PThreadParams(p)^.Num]), RT_RCDATA); // из ресурсов загружаем нужную лекцию stream.SaveToFile(tmp_filename); // сохраняем в папу Temp stream.Free; fe_res := FindExecutable(PChar(tmp_filename), nil, Buffer); // ищем приложение отображения презентаций if fe_res > 32 then // если нашли, то... begin app_filename := PChar(@Buffer); FillChar(SInfo, SizeOf(SInfo), 0); SInfo.wShowWindow := SW_SHOWNORMAL; SInfo.cb := SizeOf(SInfo); if CreateProcess(nil, PChar(Format('"%s" "%s"', [app_filename, tmp_filename])), nil, nil, False, NORMAL_PRIORITY_CLASS, nil, nil, SInfo, PInfo) then // создаем процесс с параметрами begin lpHandles[1] := PInfo.hProcess; lpHandles[0] := LectureThreadCloseEvent; // ожидаем завершение процесса или сигнала о принудительном завершении if WaitForMultipleObjects(2, @lpHandles, False, INFINITE) = WAIT_OBJECT_0 then // принудительно завершаем процесс TerminateProcess(PInfo.hProcess, 0); // подчищаем за собой CloseHandle(PInfo.hThread); CloseHandle(PInfo.hProcess); end else // уведомляем окно об ошибке запуска процесса PostMessage(PThreadParams(p)^.Wnd, WM_LECTURE_THREAD, wLECTURE_ERROR, lPROC_ERROR); end else PostMessage(PThreadParams(p)^.Wnd, WM_LECTURE_THREAD, wLECTURE_ERROR, lAPP_ERROR); // окно об ошибке (не найдено приложение для отображения презентации) Windows.DeleteFile(PChar(tmp_filename)); // удаляем временный файл PostMessage(PThreadParams(p)^.Wnd, WM_LECTURE_THREAD, wLECTURE_CLOSE, 0); // уведомляем окно о завершении потока Result := 0; ExitThread(Result); end; Запуск потока: Код:
procedure TMainForm._StartLecture(Number: TChapterNumber); var id: DWORD; begin LectureThreadParams.Wnd := Self.Handle; // задаем параметры потока LectureThreadParams.Num := Number; ResetEvent(LectureThreadCloseEvent); // сбрасываем событие принудительного завершения потока LectureThreadhandle := CreateThread(nil, 0, @LectureThreadProc, @LectureThreadParams, 0, id); // запускаем поток end; Программа запускала презентацию из ресурсов и ожидала завершения, отображая анимацию. Не забывайте подчищать за собой. Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. |
#4
|
||||
|
||||
В принципе, если Вам не важно "подвиснет" Ваша программа или нет на время выполнения стороннего приложения, то можно обойтись и без потока. Просто адаптируйте код потока под вашу задачу и вставьте его "заместо" ShellExecute.
Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. |
#5
|
|||
|
|||
Спасибо решил. Код нашел на одном из сайтов.
Код:
procedure ExecuteWait(const sProgramm: string; const sParams: string = ''; fHide: Boolean = false); var ShExecInfo: TShellExecuteInfo; begin FillChar(ShExecInfo, sizeof(ShExecInfo), 0); with ShExecInfo do begin cbSize := sizeof(ShExecInfo); fMask := SEE_MASK_NOCLOSEPROCESS; lpFile := PChar(sProgramm); lpParameters := PChar(sParams); lpVerb := 'open'; if (not fHide) then nShow := SW_SHOW else nShow := SW_HIDE end; if (ShellExecuteEx(@ShExecInfo) and (ShExecInfo.hProcess <> 0)) then try WaitForSingleObject(ShExecInfo.hProcess, INFINITE) finally CloseHandle(ShExecInfo.hProcess); end; end; Вызываю так Код:
ExecuteWait('BQuark.Rev.3.3.exe', 'Root.dat', true); |