本文整理自网络,侵删。
///<summary>创建一个进程并读取其控制台输出内容</summary>///<param name="AFileName">要执行的文件的完整路径</param>///<param name="AParams">要执行的文件命令行参数</param>///<param name="AOutputs">控制台内容输出目标</param>///<param name="APath">程序运行的当前目录,默认为 AFileName 文件所在的目录</param>///<param name="AExitCode">程序退出代码</param>///<returns>创建进程成功,返回 true,否则返回 false</returns>function DosCommand(AFileName, AParams: String; AOutputs: TStrings; APath: String = '';AExitCode:PDWORD=nil): Boolean;var sa: SECURITY_ATTRIBUTES; si: STARTUPINFO; pi: PROCESS_INFORMATION; hRead, hWrite: THandle; buffer: array [0 .. 4095] of Byte; bytesRead, bytesToRead: DWORD; TotalBytesAvail: DWORD; AStream: TBytesStream; AEncoding: TEncoding; ACode:DWORD;begin sa.nLength := sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor := nil; // 使用系统默认的安全描述符 sa.bInheritHandle := true; // 创建的进程继承句柄 if not CreatePipe(hRead, hWrite, @sa, 0) then // 创建匿名管道 begin Result := false; if Assigned(AOutputs) then AOutputs.Add(Format('匿名管道创建失败(%d):%s', [GetLastError(), SysErrorMessage(GetLastError())])); Exit; end; AStream := TBytesStream.Create; try FillChar(si, sizeof(si), 0); si.cb := sizeof(STARTUPINFO); GetStartupInfo(si); si.hStdError := hWrite; si.hStdOutput := hWrite; // 新创建进程的标准输出连在写管道一端 si.wShowWindow := SW_HIDE; // 隐藏窗口 si.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; if Length(APath) > 0 then SetCurrentDirectory(PChar(APath)) else APath:=ExtractFilePath(AFileName); if not CreateProcess(nil, PChar(AnsiQuotedStr(AFileName,'"')+' '+AParams), nil, nil, true, CREATE_NEW_CONSOLE, nil, PChar(APath), si, pi) then begin Result := false; if Assigned(AOutputs) then AOutputs.Add(Format('进程创建失败(%d):%s', [GetLastError(), SysErrorMessage(GetLastError())])); Exit; end; ACode:=0; while PeekNamedPipe(hRead, nil, 0, nil, @TotalBytesAvail, nil) do begin if TotalBytesAvail > 4096 then TotalBytesAvail := 4096; if TotalBytesAvail > 0 then begin if ReadFile(hRead, buffer, TotalBytesAvail, bytesRead, nil) then begin AStream.WriteBuffer(buffer, TotalBytesAvail); //如果要即时输出命令行内容,就应该在此尝试解析并加入到AOutputs中,此处默认不着急 end else break; end else if GetExitCodeProcess(pi.hProcess, ACode) then begin if ACode=STILL_ACTIVE then Sleep(50) else break end else break; end; if Assigned(AOutputs) and (AStream.Size>0) then begin AEncoding:=nil; TEncoding.GetBufferEncoding(AStream.Bytes, AEncoding,TEncoding.ANSI); AOutputs.Text := AEncoding.GetString(AStream.Bytes, 0, AStream.Size); end; ACode:=0; if GetExitCodeProcess(pi.hProcess, ACode) then begin Result := ACode = 0; if Assigned(AExitCode) then AExitCode^:=ACode; end else Result := false; finally CloseHandle(hWrite); CloseHandle(hRead); FreeAndNil(AStream); end;end;
用法:procedure TForm1.Button1Click(Sender: TObject);var AResult: TStringList;begin AResult := TStringList.Create; try DosCommand('C:\Windows\System32\cmd.exe', '/C dir/w', Memo1.Lines, 'c:\'); finally FreeAndNil(AResult); end;end;
来源:http://blog.qdac.cc/?p=5158
相关阅读 >>
Delphi 如何让 tgpimage 直接从流中加载图片?
更多相关阅读请进入《Delphi》频道 >>