Форум: "WinAPI";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 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!!!!




Форум: "WinAPI";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.01.08;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.75 MB
Время: 0.022 c
1-22028           tovSuhov              2001-12-18 12:16  2002.01.08  
Может кто знает...


14-22363          Дремучий              2001-11-02 18:16  2002.01.08  
Ну и ...?


3-21944           MVova                 2001-12-03 16:50  2002.01.08  
Как узнать путь к файлам?


1-22141           N                     2001-12-20 10:04  2002.01.08  
C -> Pascal: указатель на функцию внутри структуры


1-22020           Leo^Sun               2001-12-18 07:08  2002.01.08  
TMemo