lazarus 命令行调用 异步获取输出

常规的命令行调用,只能在一条命令执行完后,才能获取完整输出,而如果命令执行耗时很久,且选择了阻塞线程,就会很慢,出现卡死的假象,此时就要用到异步执行命令。

先放一篇官方文章,给出了各种命令行调用程序的方式。

Executing External Programs/zh CN - Free Pascal wiki

总结来看有以下几种方式

方法平台可单行完成功能
ExecuteProcessRTL跨平台非常有限,以同步方式执行
ShellExecuteWinAPI仅限微软的 Windows 系统很多。能够提权启动需管理员权限的程序。
fpsystem、fpexecveUnix仅限 Unix 系统
TProcessFCL跨平台完整
RunCommandFCL跨平台 需要FPC 2.6.2+支持常用的 TProcess 用法
OpenDocumentLCL跨平台只能打开文档。将会用该文档类型关联的应用程序打开。

windows平台我常用的是ShellExecute ,是标准的微软 Windows 函数(ShellApi.h),documentation on MSDN 中有完善的文档。

uses ..., ShellApi;

// 简单的单行代码调用(忽略返回错误):
if ShellExecute(0,nil, PChar('"C:\my dir\prog.exe"'),PChar('"C:\somepath\some_doc.ext"'),nil,1) =0 then;

// 执行批命令:
if ShellExecute(0,nil, PChar('cmd'),PChar('/c mybatch.bat'),nil,1) =0 then;

// 在给定目录打开命令行窗口:
if ShellExecute(0,nil, PChar('cmd'),PChar('/k cd \path'),nil,1) =0 then;

// 用“start”命令在默认浏览器中打开 URL(通过短暂显示并隐藏的 cmd 窗口):
if ShellExecute(0,nil, PChar('cmd'),PChar('/c start www.lazarus.freepascal.org/'),nil,0) =0 then;

// 助手函数:
procedure RunShellExecute(const prog,params:string);
begin
  //  ( Handle, nil/'open'/'edit'/'find'/'explore'/'print',   // 'open' 不是必需的
  //      path+prog, params, working folder,
  //        0=hide / 1=SW_SHOWNORMAL / 3=max / 7=min)   //要使用 SW_ constants 请 uses Windows 单元
  if ShellExecute(0,'open',PChar(prog),PChar(params),PChar(extractfilepath(prog)),1) >32 then; //success
  // 返回 0..32 表示出错
end;

跨平台则考虑Runcommand

function TMainForm.GetPDFPageCount(const PDFPath: string): integer;
var
  success: boolean;
  outs: string;
begin
  Result := 0;
  success := RunCommand('cmd.exe', ['/c', 'pdftk.exe ' + Utf8ToAnsi(PDFPath) + ' dump_data'], outs, [poNewProcessGroup, poUsePipes], swoHIDE);
  if success then
  begin
    Result := ExtractNumberOfPages(outs);
    //memLog.Lines.Add(pdfpath + '有' + IntToStr(Result) + '页');
    if Result = -1 then
      Result := 0;
  end;
end;

但以上这些,都不能异步。

TAsyncProcess

 异步请使用 TAsyncProcess

// 异步线程输出更新
procedure TMainForm.AsyncProcess1ReadData(Sender: TObject);
var
  AsyncProcess: TAsyncProcess absolute Sender;
  aString: string = '';
  Len: integer;
begin
  MainForm.Cursor := crHourGlass;
  Len := AsyncProcess.Output.NumBytesAvailable;
  Setlength(aString, Len);
  Len := AsyncProcess.Output.Read(aString[1], Len);
  astring := Trim(aString);

  if Pos('Analysis', astring) > 0 then
  begin
    UpdateProgress(40);
    LogOutput('正在分析Python文件...');
  end
  else if Pos('Building', astring) > 0 then
  begin
    UpdateProgress(60);
    LogOutput('正在构建EXE文件...');
  end
  else if Pos('Copying', astring) > 0 then
  begin
    UpdateProgress(80);
    LogOutput('正在复制必要文件...');
  end
  else if (Pos('ERROR:', astring) > 0) or (Pos('Error:', astring) > 0) then
    LogOutput('错误: ' + astring);
  Application.ProcessMessages;
end;
    ASyncProcess1.CommandLine := Cmd;
    ASyncProcess1.Options := [poUsePipes, poStdErrToOutPut];
    ASyncProcess1.Execute;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值