Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.04.20;
Скачать: CL | DM;

Вниз

Отслеживание исполнения   Найти похожие ветки 

 
zdm   (2008-03-27 09:21) [0]

Добрый день.
Исходные данные.
Нобходимо приложение, которое выполняет функцию копирования файлов, их архивирование и отправку по эл.почте
Копирование выполнено CopyFile, архивирование Winexec ("rar a ...") или ShellExecute (это непринципиально), Отпарвка по эл.почте средствами INDY.
Загвоздка.
При архивации вызывается внешнее приложение (rar) , а код естественно "бежит дальше"и пытается отправить то, что еще находится в процессе архивирования.
Вопрос.
Как выходить из таких ситуаций? т.е. добиться ожидания окончания процесса, чтобы продолжить код дальше

Вызывать ShowMessage, можно, но не красиво, это я могу дожидаться окончания, а юзер точно жмахнет "OK".
Таймер выставлять, тут тоже непонятно. В зависимости от производительности и загружености компа я незнаю на сколько выставлять.
С чем то подобным я сталкивался, очень давно, выход находил как FindWindow // т.е. циклил поиск окна, пока он живо ни чего не делать.. но как-то это криво, может Вы сталкивались с чем-то подобным?


 
Palladin ©   (2008-03-27 09:24) [1]

CreateProcess + WaitForSingleObject


 
zdm77   (2008-03-27 09:29) [2]


> Palladin ©   (27.03.08 09:24) [1]


Я мало сталкивался с распоралеливанием.. у Вас нет ссылок где об этом можно почитать поподробней. Заранее спасибо.


 
zdm77   (2008-03-27 09:40) [3]

Накопал инфу. пасиба. Снимаю вопрос.


 
Оригинал   (2008-03-27 14:13) [4]


> zdm77   (27.03.08 09:40) [3]
> Накопал инфу. пасиба. Снимаю вопрос.


Обрати внимание на WinExec.


 
Оригинал   (2008-03-27 14:16) [5]


> zdm77   (27.03.08 09:40) [3]
> Накопал инфу. пасиба. Снимаю вопрос.


Обрати внимание на WinExec.


 
Palladin ©   (2008-03-27 14:17) [6]


>  [4] Оригинал   (27.03.08 14:13)

И что же там интересного?


 
Kolan ©   (2008-03-27 14:17) [7]

> это непринципиально

Видишь, оказывается принципиально. :)

Вот пример:

{************************************************************}
{                                                            }
{                       KRunApplication                      }
{                Copyright © 2007  KSoftWare               }
{                                                            }
{                                                            }
{  Разработчик: Товеровский Николай                          }
{  Модифицирован: 14 декабря 2007                            }
{                                                            }
{************************************************************}
unit KRunApplication;

interface
uses
 Windows, SysUtils, Forms;
type
 {ERunApplicationException — предок для всех исключений
   генерируемых в этом модуле.}
 ERunApplicationException = class(Exception);

 {IConsoleViewVisitor — интерфейс посетителя,
   умеющего отображать данные из консоли.}
 IConsoleViewVisitor = interface
   ["{F37E51D8-7E2A-4AC1-B090-8F38F860B48A}"]
   procedure ViewConsoleMessage(const Msg: string);
 end;

 {RunApplicationAndWaitTillFinish — функция для запуска процесса
 и ожидания его завершения.

 Для того, чтобы иметь возможность обработать полученные из консоли данные
 в процедуру надо передать объект, поддерживающий интерфейс IConsoleViewVisitor
 (паттерн Visitor).

 *Не стоит использовать её в доп. потоках.
 *Не забывайте, что при реализации интерфейса производится подсчет ссылок
   и ваш объект может быть удален автоматически. Для предотвращения такого
   поведения можно унаследовать класс от TInterfacedPersistent, или реализовать
   нужную функциональность вручную.}
 procedure RunApplicationAndWaitTillFinish(RunString: string;
   ConsoleViewVisitor: IConsoleViewVisitor = nil);
implementation  

procedure RunApplicationAndWaitTillFinish(RunString: string;
   ConsoleViewVisitor: IConsoleViewVisitor);
var
 StartupInfo: TStartupInfo;
 SecurityAttributes: TSecurityAttributes;
 ProcessInfo: TProcessInformation;
 StdOutPipeRead, StdOutPipeWrite: THandle;
 CreateResult: Boolean;
 S: string;
 BytesReadFromFile: Cardinal;
 BytesReadFromPipe: Cardinal;
 WaitResult: Cardinal;
begin
 with SecurityAttributes do
 begin
   nLength := SizeOf(SecurityAttributes);
   bInheritHandle := True;
   lpSecurityDescriptor := nil;
 end;
 
 {Создать пайп для перенаправления стандартного вывода.}
 if not CreatePipe(
   StdOutPipeRead, // дескриптор чтения.
   StdOutPipeWrite, // дескриптор записи.
   @SecurityAttributes, // аттрибуты безопасности.
   0) // количество байт принятых для пайпа — 0 по умолчанию.
 then
   raise ERunApplicationException.Create(SysErrorMessage(GetLastError));
 try
 
   with StartupInfo do
   begin
     FillChar(StartupInfo, SizeOf(StartupInfo), 0);
     cb := SizeOf(StartupInfo);
     dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
     wShowWindow := SW_HIDE;
     hStdInput := GetStdHandle(STD_INPUT_HANDLE); // стандартный ввод не перенаправляем
     hStdOutput := StdOutPipeWrite;
     hStdError := StdOutPipeWrite;
   end;

   ZeroMemory(@ProcessInfo, SizeOf(@ProcessInfo));

   CreateResult := CreateProcess(nil, PAnsiChar(RunString), nil, nil, True,
     0, nil, nil, StartupInfo, ProcessInfo);

   if CreateResult then
   begin
     try
       repeat
         Application.ProcessMessages;
         {Ждать процесс 100 мс.}
         WaitResult := WaitForSingleObject(ProcessInfo.hProcess, 100);
         Application.ProcessMessages;
         {Узнать сколько в пайпе байт}
         PeekNamedPipe(StdOutPipeRead, nil, 0, nil, @BytesReadFromPipe, nil);
         {Есл байт больше 0&#133}
         if BytesReadFromPipe > 0 then
         begin
           {&#133 выделить память для строки.}
           SetLength(S, BytesReadFromPipe);
           {Прочесть байты.}
           if not ReadFile(StdOutPipeRead, PChar(S)^, BytesReadFromPipe, BytesReadFromFile, nil) then
             raise ERunApplicationException.Create(SysErrorMessage(GetLastError));
           {Отрезать лишние.}
           SetLength(S, BytesReadFromFile);
           {Перекодировать из дос кодировки.}
           OemToAnsi(PChar(S), PChar(S));
           {Отправить полученые из консоли данные посетителю.}
           if Assigned(ConsoleViewVisitor) then
             ConsoleViewVisitor.ViewConsoleMessage(S);
         end;
       {Выйти если процесс завершился и нечего читать.}
       until (WaitResult <> WAIT_TIMEOUT) and (BytesReadFromPipe = 0);
     finally
       {Закрыть хендлы процесса.}
       CloseHandle(ProcessInfo.hThread);
       CloseHandle(ProcessInfo.hProcess);
     end;
   end
   else
     raise ERunApplicationException.Create(SysErrorMessage(GetLastError));
 finally
   {Закрыть хендлы пайпа.}
   CloseHandle(StdOutPipeRead);
   CloseHandle(StdOutPipeWrite);
 end;
end;

end.


 
Оригинал   (2008-03-27 14:20) [8]


> Palladin ©   (27.03.08 14:17) [6]
> >  [4] Оригинал   (27.03.08 14:13)И что же там интересного?
>


Полностью удовлетворяет условиям задачи. Не согласен?


 
Palladin ©   (2008-03-27 14:21) [9]


> Оригинал   (27.03.08 14:20) [8]

нет конечно, ты читал вопрос то?


 
Оригинал   (2008-03-27 14:24) [10]


> Palladin ©   (27.03.08 14:21) [9]
> > Оригинал   (27.03.08 14:20) [8] нет конечно, ты читал
> вопрос то?


А ты читал? Или лень f1 нажать?


 
Palladin ©   (2008-03-27 14:26) [11]

Нет не лень, но расскажи мне. Как заставить в коде

WinExec("notepad.exe",sw_shownormal);
ShowMessage("Notepad закрыли");


сообщение "Note pad закрыли" появится после закрытия запущенного блокнота, о мудрейший...


 
Оригинал   (2008-03-27 14:37) [12]


> Нет не лень, но расскажи мне. Как заставить в кодеWinExec("notepad.
> exe",sw_shownormal);ShowMessage("Notepad закрыли");сообщение
> "Note pad закрыли" появится после закрытия запущенного блокнота,
>  о мудрейший...


Сорри. Забыл, что WinExec ждет только загрузки приложения, о блистательнейший Мастер.


 
zdm   (2008-03-28 12:13) [13]

я чегото вас не всех понял. Вчера уже все решили и получилось, Palladin © правильно наталкнул на мысль о WaitForSingleObject. Вопрос был в ожидании процесса а не какими средствами его исполнять.

я нашел с его помощью такое решение, ну например...

код в Tthread
procedure TThreadArch.Execute;
var
Source:string;
begin
   WinExec(pchar("rar a c:\1\qqq c:\1"),1);
end;


В окне где вызовется процесс
procedure TFormOsn.Button1Click(Sender: TObject);
var T1 : TThreadArch;
begin
T1:= TThreadArch.Create(false);
T1.Priority:=tpLowest;
WaitForSingleObject(T1.Handle,0); //тайм на бесконечность пока не выполнится
ShowMessage(""); //пока процесс незакончится и модалка даже не выскочит
end;


 
Оригинал   (2008-03-28 13:11) [14]


> zdm   (28.03.08 12:13) [13]
> я чегото вас не всех понял. Вчера уже все решили и получилось,
>  Palladin © правильно наталкнул на мысль о WaitForSingleObject.
>  Вопрос был в ожидании процесса а не какими средствами его
> исполнять.я нашел с его помощью такое решение, ну например.
> ..


На мысль-то натолкнул, но ты явно неправильно понял.
И непонятно, что у тебя работает.

Для получения дескриптора процесса, его нужно запускать с помощью Createprocess, а не WinExec. WinExec не ожидает завершения процесса.
WaitForSingleObject нужно применять как раз к полченному дескриптору, а ине к дескриптору потока, в котором ты запускаешь свой процесс архивации.


 
Игорь Шевченко ©   (2008-03-28 14:19) [15]


> код в Tthread
> procedure TThreadArch.Execute;
> var
> Source:string;
> begin
>    WinExec(pchar("rar a c:\1\qqq c:\1"),1);
> end;
>
> В окне где вызовется процесс
> procedure TFormOsn.Button1Click(Sender: TObject);
> var T1 : TThreadArch;
> begin
> T1:= TThreadArch.Create(false);
> T1.Priority:=tpLowest;
> WaitForSingleObject(T1.Handle,0); //тайм на бесконечность
> пока не выполнится
> ShowMessage(""); //пока процесс незакончится и модалка даже
> не выскочит
> end;


Дети Ивана Кулибина

RTFM: ShellExecuteEx


 
grisme   (2008-03-28 17:18) [16]

Оригинал   (28.03.08 13:11) [14]

а разве не:
The WaitForSingleObject function can wait for the following objects:
...
Thread The CreateProcess, CreateThread, or CreateRemoteThread function returns the handle. A thread object"s state is signaled when the thread terminates.
...


 
Palladin ©   (2008-03-28 17:22) [17]


> grisme   (28.03.08 17:18) [16]

ты разницу между дескриптором TThreadArch и дескриптором процесса созданного WinExec ощущаешь? или тебе пофиг, лишь бы дескриптор? любой подставляй и работать будет


 
Германн ©   (2008-03-28 17:28) [18]


> Для получения дескриптора процесса, его нужно запускать
> с помощью Createprocess

Так у Createprocess туева хуча параметров! Задолбаешься их понять!
:-)


 
grisme   (2008-03-28 17:42) [19]


> Palladin ©   (28.03.08 17:22) [17]


ну, теперь ощущаю, tnx -- будем знать :-) в отмазку(эх...) скажу, что классу TThread со мной не работалось %)



Страницы: 1 вся ветка

Текущий архив: 2008.04.20;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.015 c
2-1206555175
junkie
2008-03-26 21:12
2008.04.20
Excel процесс остается в памяти


6-1185196401
Newfrost
2007-07-23 17:13
2008.04.20
idHTTP и проблемы с кодировкой


15-1204899711
Kolan
2008-03-07 17:21
2008.04.20
Чем же все таки работать с базами SQLite?


2-1206563385
vromav
2008-03-26 23:29
2008.04.20
Преобразование типов


15-1204627499
tytus
2008-03-04 13:44
2008.04.20
Посоветуйте прогу обнаружения шпионов и Downloader-ов