Форум: "Начинающим";
Текущий архив: 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…}
if BytesReadFromPipe > 0 then
begin
{… выделить память для строки.}
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