Форум: "WinAPI";
Текущий архив: 2002.01.08;
Скачать: [xml.tar.bz2];
ВнизWinExec непонятка Найти похожие ветки
← →
Besa (2001-09-11 11:11) [0]Доброго времени суток! Непонятка вот в чем: WinExec в примере приведенном ниже работает нормально
WinExec("arj a c:\temp\Db.arj c:\temp\Db.txt", SW_SHOW)
но если я пытаюсь передать переменную(см. ниже)
1 вар.
WinExec("arj a c:\temp\Db"+ ORG + ".arj c:\temp\Db" + "ORG" + ".txt", SW_SHOW)
2 вар.
WinExec(Str1, SW_SHOW)
выбивает ошибку:
[Error] Unit1.pas(88): Incompatible types: "String" and "PChar"
причем DeleteFile работает нормально
пример кода:
var DUBL, ORG, Str1:String;
i,y:Integer;
F :System.Text;
begin
Query1.Active:=True;
Query1.First;
ORG:=Query1.FieldByName("pr_org").AsString;
Str1:="arj a c:\temp\Db" + ORG + ".arj c:\temp\Db" + ORG + ".txt";
if WinExec("arj a c:\temp\Db"+ ORG + ".arj c:\temp\Db" + "ORG" + ".txt", SW_SHOW) < 32
then
begin
end
else
if deletefile("c:\temp\Db"+ORG+".txt")
then
ShowMessage( DELETE !")
else
ShowMessage(" Not DELETE !");
подскажите,плс, в чем я не прав
← →
Digitman (2001-09-11 11:29) [1]WinExec(PChar(Str1), SW_SHOW)
а что, по твоему разницы между string и PChar нет никакой ? глубоко заблуждаешься !
← →
Юрий Зотов (2001-09-11 11:32) [2]В том, что передаете параметр типа string там, где требуется PChar. В случае константы компилятор все делает сам, а в случае переменной надо использовать явное приведение типа:
WinExec(PChar("arj a c:\temp\Db" + ORG + ".arj c:\temp\Db" + "ORG" + ".txt"), SW_SHOW);
WinExec(PChar(Str1), SW_SHOW);
← →
Besa (2001-09-11 11:43) [3]>All
Cпасибо!
Вы уж простите неуча, что отвлекаю... :)
← →
Besa (2001-09-11 19:09) [4]>All
Опять неуч беспокоит
WinExec возвращает код завершения > 31, то выполнено...
вопрос:
1)отработала данная вызванная программа(в смысле ждет ли завершения выполнения внешней проги)? т.е. в данном примере возможно ли удаление раньше архивации?
2) как можно получить errorlevel от внешней программы
3) хотелость бы узнать - это и все коды завершения возвращаемые сабжем
0 The system is out of memory or resources.
ERROR_BAD_FORMAT The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).
ERROR_FILE_NOT_FOUND The specified file was not found.
ERROR_PATH_NOT_FOUND The specified path was not found.
Заранее благодарен
← →
Юрий Зотов (2001-09-11 22:40) [5]1. Нет, не ждет. Просто запускает - и все, а что будет дальше - никому не известно.
2. Получить хэндл ее процесса, а затем дождаться ее завершения и вызвать GetExitCodeProcess.
3. В хелпе других кодов нет. Надо полагать, это все.
Похоже, Вам нужно ипользовать функцию CreateProcess, которая позволяет легко совместить все "в одном флаконе". Вот рабочий пример запуска внешней программы с ожиданием ее завершения, получением кода возврата и вызовом обработчика события при завершении.
unit Unit1;
interface
uses
SysUtils, Classes, Controls, Forms, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
procedure ThreadFinished(Sender: TObject);
end;
var
Form1: TForm1;
implementation
uses
Unit2;
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
// Создаем и настраиваем второй поток. Он запустит внешнюю программу,
// дождется ее завершения, вызовет наш обработчик и даст код возврата.
with TMyThread.Create(False) do
begin
CommandLine := "Notepad.exe AutoExec.bat"; // Подставьте свое
WorkingDirectory := "C:\"; // Подставьте свое
OnTerminate := ThreadFinished
end
end;
procedure TForm1.ThreadFinished(Sender: TObject);
begin
// Внешняя программа завершилась. Второй поток больше не нужен.
with TMyThread(Sender) do
begin
Caption := IntToStr(ExitCode);
Free
end
end;
end.
=========================================
unit Unit2;
interface
uses
Windows, Classes;
type
TMyThread = class(TThread)
private
FCommandLine: string;
FWorkingDirectory: string;
FExitCode: DWORD;
protected
procedure Execute; override;
public
property CommandLine: string read FCommandLine write FCommandLine;
property WorkingDirectory: string read FWorkingDirectory write FWorkingDirectory;
property ExitCode: DWORD read FExitCode;
end;
implementation
procedure TMyThread.Execute;
var
SI: TStartupInfo;
PI: TProcessInformation;
begin
// Готовим структуру SI
ZeroMemory(@SI, SizeOf(SI));
SI.cb := SizeOf(SI);
// Пытаемся запустить внешнюю программу
if CreateProcess(nil, PChar(FCommandLine), nil, nil, False, 0, nil, PChar(FWorkingDirectory), SI, PI) then
begin
CloseHandle(PI.hThread); // Освобождаем ненужные системные ресурсы
// Ждем завершения с проверкой Terminated 1 раз в секунду.
while not Terminated and (WaitForSingleObject(PI.hProcess, 1000) = WAIT_TIMEOUT) do;
// Или получаем, или формируем код возврата (должна стоять короткая булевская схема)
if Terminated or not GetExitCodeProcess(PI.hProcess, FExitCode) then FExitCode := $FFFFFFFF;
CloseHandle(PI.hProcess) // Освобождаем ненужные системные ресурсы
end
else FExitCode := GetLastError // Запуск не получился, узнаем причину
end;
end.
← →
Besa (2001-09-12 09:56) [6]> Юрий Зотов
ОГРОМНОЕ СПАСИБО!
Накопал еще коды завершения в книге Архангельского "Делфи 5"
если надо могу перепечатать и вывесить, спрашиваю не потому что лень, а по тому чтоб не делать двойной работы, если это уже сделали другие на этом сайте.
И еще, Юрий, могу ли я ссылаясь на Вас дополнить статью
http://delphi.mastak.ru/articles/winexec/index.html
с Вашим примером, т.к. в данной статье насколько я понял описано на русском языке help дельфи и не сказано о взаимодействии с внешними прогами?
← →
Юрий Зотов (2001-09-12 15:24) [7]Дополните, если есть желание, дело полезное, почему бы и нет. Только, я думаю, прежде, чем дополнять статью, надо бы получить согласие ее автора, Михаила Подмогова. Или писать свою, самостоятельную статью.
И еще. Если FWorkingDirectory - пустая строка (а это вполне нормально и запросто может быть), то PChar(FWorkingDirectory) даст ошибку. В этом случае в соответствующем параметре CreateProcess надо передавать просто nil и поэтому код метода TMyThread.Execute желательно немного доработать. Например, так:
var
PWorkDir: PChar; // Еще одна локальная переменная в Execute.
...
if FWorkingDirectory = ""
then PWorkDir := nil
else PWorkDir := @FWorkingDirectory[1];
И теперь передаем PWorkDir.
Впрочем, можно и оставить, как есть, просто упомянуть в тексте. "Поимку в пустыне Сахара ручного льва предоставляем читателю в качестве самостоятельного упражнения" (из книги "Физики шутят").
← →
Besa (2001-09-12 17:20) [8]>Юрий Зотов
Спасибо!
Письмо Михаилу, я уже отправил. Буду ждать ответа.
на свою силенок может не хватить, но попробую.
← →
handra (2001-09-12 19:24) [9]Еще один вариант запусти и дождаться завершения:
function ExecAndWait(const fname,params: string; nShowCmd: Cardinal): boolean;
var data: TShellExecuteInfo;
begin
Result := false;
data.cbSize := sizeof(data);
data.fMask := SEE_MASK_DOENVSUBST or SEE_MASK_NOCLOSEPROCESS;
data.Wnd := 0;
data.lpVerb := nil;
data.lpFile := PChar(fname);
data.lpParameters := PChar(params);
data.lpDirectory := nil;
data.nShow := nShowCmd;
ShellExecuteEx(@data);
while true do begin
Application.ProcessMessages;
case WaitForSingleObject(data.hProcess,100) of
WAIT_FAILED: Result := false;
WAIT_OBJECT_0: Result := true;
else continue;
end;
break;
end;
end;
← →
Delirium (2001-10-08 18:59) [10]А слабо просто WinExec(PChar("....."),SW_SHOW) ?
← →
vovan1 (2001-11-07 18:15) [11]Господа, помогите пожалуйста! Попробовал код приведенный Ю.Озеровым, работает, но проблема такая: как запихнуть в архив несколько файлов? Если я делаю цикл, с вызыванием архиватора в отдельном потоке для каждого файла, то у меня в архив попадают только один-или два файла, а надо четыре! Как выйти из данной ситуации? Как тормозуть выполнение следующего процесса, до тех пор, пока предыдущий не отработает? HELP!!!!
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2002.01.08;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.007 c