开仓放粮了: delphi在命令行执行命令时的2个问题? Delphi / Windows SDK/APIhttp://www.delphi2007.net/DelphiAPI/html/delphi_20061120203959190.html
1: 怎么等待命令执行完后再执行下面的语句
2: 怎么捕获命令产生的错误,并提示出来?
第2个问题值150分啊
1 用WaitForSingleObject
2 var a:TStringList;
begin
a:=TStringList.Create;
try
a.LoadFromFile('123.txt'); //不存在这个文件
except
on E: Exception do
Showmessage('出错:' + E.message);
a.Free
end;
end;
用WaitForSingleObject可行。。
try
except
on e: exception do
showmessage(e.message)
end;
这种方法是可行的
还有一种办法在你程序的界面放一个ApplicationEvents 这个控件
在它的Exception事件里写代码
procedure Tfrmo1.ApplicationEvents1Exception(Sender: TObject;
E: Exception);
Sender就是你的对象 而Exception就是异常
第一个问题用sleep(1000) 就可以解决了吧~~~
可参考下<delphi源代码分析>
1.用WaitForSingleObject
procedure TForm1.Button1Click(Sender: TObject);
var
MutexHandle:THandle;
begin
WaitForSingleObject(MutexHandle,INFINITE);
//do your code
CloseHandle(MutexHandle);
end;
2.var
List:TStringList;
begin
List:=TStringList.Create;
try
//do something error
except
on E: Exception do
Showmessage(E.message);
a.Free
end;
end;
JF。。.
第2个问题用debug
有错的话就debug
抢分!
JF。。。。
路过。
jf
1 用WaitForSingleObject
2 try
except
on E: Exception
大家怎么不看楼主是几个星星的~~~
try
except
他会不知道〉?
如果楼主的命令是指DOS命令行的话, 则必须使用
CreateProcess 建议命令进程
然后使用Wait函数(如: WaitForSingleObject) 等待进程的Handle
接粮
接粮
再接粮
接分
第1个问题:
function WinExecAndWait32(
FileName: string; Visibility: integer): integer;
var
zAppName: array[0..512] of char;
zCurDir: array[0..255] of char;
WorkDir: string;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
ExitCode: DWORD;
begin
StrPCopy(zAppName, FileName);
GetDir(0, WorkDir);
StrPCopy(zCurDir, WorkDir);
FillChar(StartupInfo, Sizeof(StartupInfo), #0);
StartupInfo.cb := Sizeof(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := Visibility;
if not CreateProcess(nil, zAppName,
{ pointer to command line string }
nil, { pointer to process security attributes }
nil, { pointer to thread security attributes }
false, { handle inheritance flag }
CREATE_NEW_CONSOLE or { creation flags }
NORMAL_PRIORITY_CLASS,
nil, { pointer to new environment block }
nil, { pointer to current directory name }
StartupInfo, { pointer to STARTUPINFO }
ProcessInfo) then Result := -1
{ pointer to PROCESS_INF }
else begin
WaitforSingleObject(ProcessInfo.hProcess, INFINITE);
GetExitCodeProcess(ProcessInfo.hProcess, ExitCode);
Result:=ExitCode;
end;
end;
第2个没试过
procedure CaptureConsoleOutput(DosApp : string;AMemo : TMemo);
const
ReadBuffer = 1048576; // 1 MB Buffer
var
Security : TSecurityAttributes;
ReadPipe,WritePipe : THandle;
start : TStartUpInfo;
ProcessInfo : TProcessInformation;
Buffer : Pchar;
TotalBytesRead,
BytesRead : DWORD;
Apprunning,n,
BytesLeftThisMessage,
TotalBytesAvail : integer;
begin
with Security do
begin
nlength := SizeOf(TSecurityAttributes);
binherithandle := true;
lpsecuritydescriptor := nil;
end;
if CreatePipe (ReadPipe, WritePipe, @Security, 0) then
begin
// Redirect In- and Output through STARTUPINFO structure
Buffer := AllocMem(ReadBuffer + 1);
FillChar(Start,Sizeof(Start),#0);
start.cb := SizeOf(start);
start.hStdOutput := WritePipe;
start.hStdInput := ReadPipe;
start.dwFlags := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW;
start.wShowWindow := SW_HIDE;
// Create a Console Child Process with redirected input and output
if CreateProcess(nil ,PChar(DosApp),
@Security,@Security,
true ,CREATE_NO_WINDOW or NORMAL_PRIORITY_CLASS,
nil ,nil,
start ,ProcessInfo) then
begin
n:=0;
TotalBytesRead:=0;
repeat
// Increase counter to prevent an endless loop if the process is dead
Inc(n,1);
// wait for end of child process
Apprunning := WaitForSingleObject(ProcessInfo.hProcess,100);
Application.ProcessMessages;
// it is important to read from time to time the output information
// so that the pipe is not blocked by an overflow. New information
// can be written from the console app to the pipe only if there is
// enough buffer space.
if not PeekNamedPipe(ReadPipe ,@Buffer[TotalBytesRead],
ReadBuffer ,@BytesRead,
@TotalBytesAvail,@BytesLeftThisMessage) then break
else if BytesRead > 0 then
ReadFile(ReadPipe,Buffer[TotalBytesRead],BytesRead,BytesRead,nil);
TotalBytesRead:=TotalBytesRead+BytesRead;
until (Apprunning <> WAIT_TIMEOUT) or (n > 150);
Buffer[TotalBytesRead]:= #0;
OemToChar(Buffer,Buffer);
AMemo.Text := AMemo.text + StrPas(Buffer);
end;
FreeMem(Buffer);
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ReadPipe);
CloseHandle(WritePipe);
end;
end;
我来回答第二个问题。 上边回答的都是自己的程序出异常,实际中,你在调用外部程序发生异常后出错时,一般的程序都会将错误输出到标准错误(STDERR),所以,你只要能读到他的STDERR或STDOUT(标准输出)就行了.
读取方法:
1.象楼上那样,用一个命名管道
2.有一个控件的,名字不记得了....
3.加上命令行参数,将标准输出和错误输出存到文件中....如下:
mCommand := "test.exe >a.txt 2>b.txt";
winexec(mCommand);
这样在执行过后,标准输出就写入了 a.txt, 错误输出就写入了b.txt
不一定能帮上你的忙,只是提供一个思路.
文章来源:
http://www.delphi2007.net/DelphiAPI/html/delphi_20061120203959190.html