Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.04.20;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.048 c
15-1204819301
Пробегал...
2008-03-06 19:01
2008.04.20
Переход по CTRL + клик глючит


2-1206282811
Илья
2008-03-23 17:33
2008.04.20
Подскажите, как можно перехватить все запускающиеся приложения?


2-1206716738
Kolan
2008-03-28 18:05
2008.04.20
Не удается присвоить значение полю структуры в объекте.


2-1206104117
Pavelkq
2008-03-21 15:55
2008.04.20
Чтение цвета заливки в RichEdit


8-1178783833
Veter
2007-05-10 11:57
2008.04.20
удаление TShape





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский