![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Почему иногда файл не проходит полностью через MS Outlook?
Razrab © (2007-12-19 16:05:00)Добрый день, мастера! :) Подскажите по поводу возникшей проблемы. Вначале формирую rar-файл, посредством:
ShellExecute(handle,'open', 'winrar.exe',
PChar('m -ibck '+selFileName+' 1f.sql 2f.sql'),PChar(Current_Dir),sw_show);
Затем отпраляю этот файл через клиент MS Outlook на определенный адрес, с помощью следующей процедуры:
procedure SendOutlookMail;
const
olMailItem = 0;
var
Outlook: OleVariant;
vMailItem: variant;
begin
try
Outlook := GetActiveOleObject('Outlook.Application');
except
Outlook := CreateOleObject('Outlook.Application');
end;
vMailItem := Outlook.CreateItem(olMailItem);
vMailItem.Recipients.Add('ivanov@workmail.ru');
vMailItem.Subject := 'Заголовок';
vMailItem.Body := 'Тело письма';
vMailItem.Attachments.Add(selFileName);
vMailItem.Send;
VarClear(Outlook);
end;
где selFileName - полный путь к созданному и прикрепленному к письму rar-файлу.
Но возникает следующая проблема - файл не всегда проходит полностью. Весь архив занимает 3 Мб, а бывают ситуации, когда файл приходит с размером 1 Мб или 2 Мб, соответственно WinRar его открыть не может - битый архив. Но самое непонятное, что такое бывает не всегда и порой все может пройти по почте абсолютно нормально - нормальный архив в 3 Мб. При этом сам rar-файл на диске ВСЕГДА формируется нормально - 3 Мб, а вот именно по почте может пройти битым. В чем причина, не пойму? Ограничение на размер присоединяемых файлов куда более 3 Мб. Подскажите, где здесь может быть проблема? Заранее благодарю.
clickmaker (2007-12-21 13:25:00) [1]
> PChar(' '
зачем пробел?
CreateProcess(nil, 'winrar.exe ' + Pchar(selFileName+' sprav.sql abont.sql'), ...
Razrab (2007-12-21 12:27:00) [2]Проблема! Код:
> CreateProcess(PChar('winrar.exe'), PChar(' '+selFileName+'
> sprav.sql abont.sql'), nil, nil, false, high_priority_class,
> nil, nil, StartInfo, ProcInfo);
почему-то не срабатывает, пишет неверный путь. Подскажите в чем причина, а то я с CreateProcess до этого не работал.
Kolan (2007-12-20 13:40:00) [3]> было бы корректнее всетаки засунуть фпоток :)
Не доделал, поэтому и хинт
Slym (2007-12-20 07:30:00) [4]Kolan © (19.12.07 17:22) [6]
*Не стоит использовать её в доп. потоках.
было бы корректнее всетаки засунуть фпоток :)
Kolan © (19.12.07 17:22) [6]
RunApplicationAndWaitTillFinish(' rar.exem —ibck '+selFileName+' 1f.sql 2f.sql',nil);
Kolan (2007-12-19 17:22:00) [5]> Вот именно. Ты что думал что ShellExecute вернет тебе управление
> когда WinRar уже все сделает?
Надо юзать CreateProcess и ждать завершения.
Вот буквально обсуждал на форуме про dts
{************************************************************}
{ }
{ KRunApplication }
{ Copyright © 2007 KSoftWare }
{ }
{ }
{ Разработчик: Товеровский Николай }
{ Модифицирован: 14 декабря 2007 }
{ }
{************************************************************}
unit KRunApplication;
interface
uses
Windows, SysUtils, Forms;
type
{IConsoleViewVisitor интерфейс посетителя,
умеющего отображать данные из консоли.}
IConsoleViewVisitor = interface
procedure ViewConsoleMessage(Msg: string);
end;
{RunApplicationAndWaitTillFinish функция для запуска процесса
и ожидания его завершения.
Для того, чтобы иметь возможность обработать полученные из консоли данные
в процедуру надо передать объект, поддерживающий интерфейс IConsoleViewVisitor
(паттерн Visitor).
*Не стоит использовать её в доп. потоках.
*Не забывайте, что при реализации интерфейса производится подсчет ссылок
и ваш объект может быть удален автоматически. Для предотвращения такого
поведения можно унаследовать класс от TInterfacedPersistent, или реализовать
нужную функциональность вручную.}
procedure RunApplicationAndWaitTillFinish(RunString: string;
ConsoleViewVisitor: IConsoleViewVisitor);
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
RaiseLastOSError;
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
RaiseLastOSError;
{Отрезать лишние.}
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
RaiseLastOSError;
finally
{Закрыть хендлы пайпа.}
CloseHandle(StdOutPipeRead);
CloseHandle(StdOutPipeWrite);
end;
end;
end.
Можешь вызвать так:
RunApplicationAndWaitTillFinish('winrar.exe m ibck '+selFileName+' 1f.sql 2f.sql',
nil);
Kolan (2007-12-19 17:18:00) [6]> А если по времени, то rar-файл формируется где-то минут
> 7.
7 минут 3 метровый архив 0_o
Германн (2007-12-19 17:18:00) [7]
> Да, а письмо приходит через пару минут.
>
Вот именно. Ты что думал что ShellExecute вернет тебе управление когда WinRar уже все сделает?
Razrab (2007-12-19 17:14:00) [8]Да, а письмо приходит через пару минут.
Razrab (2007-12-19 17:11:00) [9]Германн
В смысле "происходит"? В коде следующая строчка:
ShellExecute (....);
SendOutlookMail;
А если по времени, то rar-файл формируется где-то минут 7.
Германн (2007-12-19 17:04:00) [10]
> Подскажите, где здесь может быть проблема?
Вначале ShellExecute
Затем отправляешь.
А как быстро происходит "затем"?
P.S.
deja vu