Форум по Delphi программированию

 



Вернуться   Форум по Delphi программированию > Все о Delphi > Синтаксис
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 02.05.2020, 21:31
rodionov_uv rodionov_uv вне форума
Прохожий
 
Регистрация: 23.01.2017
Сообщения: 9
Версия Delphi: Delphi7
Репутация: 10
По умолчанию Как отловить закрытие запущенного приложения

Запускаю из своего приложения стороннюю программу, с помощью 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  
Старый 04.05.2020, 19:14
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,607
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Из ShellExecute - никак.
Тебе надо использовать CreateProcess. В этом случае ты получишь некоторый Handle, который можно проверять на валидность. Как только он освободится - значит приложение закрылось.
Ответить с цитированием
  #3  
Старый 05.05.2020, 10:42
Аватар для dr. F.I.N.
dr. F.I.N. dr. F.I.N. вне форума
I Like it!
 
Регистрация: 12.12.2009
Адрес: Россия, г. Новосибирск
Сообщения: 647
Версия Delphi: D6/D7
Репутация: 26643
По умолчанию

С одного старого проекта вырезка:

Код:
  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  
Старый 05.05.2020, 10:52
Аватар для dr. F.I.N.
dr. F.I.N. dr. F.I.N. вне форума
I Like it!
 
Регистрация: 12.12.2009
Адрес: Россия, г. Новосибирск
Сообщения: 647
Версия Delphi: D6/D7
Репутация: 26643
По умолчанию

В принципе, если Вам не важно "подвиснет" Ваша программа или нет на время выполнения стороннего приложения, то можно обойтись и без потока. Просто адаптируйте код потока под вашу задачу и вставьте его "заместо" ShellExecute.
__________________
Грамотно поставленный вопрос содержит не менее 50% ответа.
Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть.
Ответить с цитированием
  #5  
Старый 05.05.2020, 16:01
rodionov_uv rodionov_uv вне форума
Прохожий
 
Регистрация: 23.01.2017
Сообщения: 9
Версия Delphi: Delphi7
Репутация: 10
По умолчанию

Спасибо решил. Код нашел на одном из сайтов.

Код:
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);
Ответить с цитированием
  #6  
Старый 05.05.2020, 19:29
Аватар для dr. F.I.N.
dr. F.I.N. dr. F.I.N. вне форума
I Like it!
 
Регистрация: 12.12.2009
Адрес: Россия, г. Новосибирск
Сообщения: 647
Версия Delphi: D6/D7
Репутация: 26643
По умолчанию

так, для ознакомления
__________________
Грамотно поставленный вопрос содержит не менее 50% ответа.
Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть.
Ответить с цитированием
Ответ



Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 11:44.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2020

ВКонтакте   Facebook   Twitter