while (WaitforSingleObject(LProceInfo.hProcess, 100) = WAIT_TIMEOUT) do begin ReadLinesFromPipe(False); //Application.ProcessMessages; //if Application.Terminated then break; end; ReadLinesFromPipe(True);
这楼主是个憨憨, 说给它一个类文件, 它说只想要个函数. Qc := QShell.Create; // 无限等待. Qc.Timeout := 0; // 调用命令行看名字应该是ffmpeg. Qc.Exec(video.FFmpeg, CMMD); // 无限循环, 第一个判断是手工中止, 第二个判断是退出程序. 但凡一个条件为true, 退出循环. while Qc.ExecWait((btn_zmcon.Hint = '') or IS_CLOSE) do begin // 很多人觉得命令行是一行一行输出, 实际没那么简单. if Qc.ExecLines.Count > 0 then begin // 如果有新的输出, 循环读出来. for s in Qc.ExecLines do begin
ExecWait 方法才是精华. function QShell.ExecWait(WaitStop:Boolean=False): Boolean; var inS: TStream; WTi:Integer; WErrCode:Cardinal; Dest: AnsiString; Avail: DWORD; begin SetLength(Dest, 1024); ExecLines.Clear; Result := False; try if (not WaitStop) and Handle and (ProcessAppMessage) AND (not Application.Terminated) and (not IsExecEnd) then begin WTi := 0; while True do begin Application.ProcessMessages; WErrCode := WaitForSingleObject(PI.hProcess, 100); inc(WTi, 100); Inc(RunTime,100); if WTi >= ExecWaitTime then Break; if IsExecEnd then Break; if Application.Terminated then Break; end;
Result := True; if (WErrCode <> WAIT_TIMEOUT) then begin IsExecEnd := true; end else if (Timeout <> 0) and (RunTime >= Timeout) then begin //超时. WErrCode := WAIT_TIMEOUT; IsExecEnd := true; end; Info.ForceName('SingleObject').AsInteger := WErrCode; Info.ForceName('WaitForTime').AsInt64 := RunTime; Info.ForceName('WaitErrCode').AsInteger := WErrCode; Info.ForceName('WaitErrMsg').AsString := SysErrorMessage(WErrCode); end else begin // 如果它并没完全完成, 添加错误码值. if ErrCode = 0 then begin if not ProcessAppMessage then begin ErrCode := 995; ErrMsg := SysErrorMessage(ErrCode); end else if WaitStop then begin ErrCode := 1223; ErrMsg := SysErrorMessage(ErrCode); end else if not Handle then begin ErrCode := 1830; ErrMsg := SysErrorMessage(ErrCode); end else if Application.Terminated then begin ErrCode := 1235; ErrMsg := SysErrorMessage(ErrCode); end; Info.ForceName('ErrCode').AsInteger := ErrCode; Info.ForceName('ErrMsg').AsString := SysErrorMessage(ErrCode); end; end;
if PeekNamedPipe(StdOutPipeRead, @Dest[1], 1024, @Avail, nil, nil) then begin if Avail > 0 then begin inS := THandleStream.Create(StdOutPipeRead); try if inS.Size > 0 then begin try TemStrQ.Clear; TemStrQ.CopyFrom(inS,ins.Size); TemStrQ.Position := 0; ExecLines.Clear; ExecLines.LoadFromStream(TemStrQ,TEncoding.UTF8); except on E: Exception do begin TemStrQ.Position := 0; ExecLines.Clear; ExecLines.LoadFromStream(TemStrQ); end; end;
// 识别异常. if (ExecLines.Count > 0) AND (Pos('**#11021#**', ExecLines.Text) > 0) then begin ExecLines.Text := Trim(StringReplace(ExecLines.Text,'**#11021#**','',[rfReplaceAll])); // 这是dos 错误. 但不会阻止循环. if ErrCode = 0 then begin ErrCode := 119; ErrMsg := SysErrorMessage(ErrCode); Info.ForceName('ErrCode').AsInteger := ErrCode; Info.ForceName('ErrMsg').AsString := ErrMsg; end; end;
if (not IsNotRetData) AND (ExecLines.Count > 0) then begin OutStrings.AddStrings(ExecLines); end; end; finally FreeAndNil(inS); end; end; end; // 释放监控信息在json里面。 with Info do begin ForceName('isNotTerminateApp').AsBoolean := isNotTerminateApp; ForceName('SetTimeout').AsInteger := Timeout; ForceName('IsNotRetData').AsBoolean := IsNotRetData; ForceName('ExecCount').AsInteger := (ForceName('ExecCount').AsInteger+1); ForceName('ExecResult').AsBoolean := Result; ForceName('EndDate').AsString := FormatDateTime('yyyy-mm-dd hh:nn:ss',now()); end; finally // 如果返回假,可能情况是已经退出, 或者超时, 清理pid之类。 if not Result then begin DoEnd; if not IsNotRetData then begin Info.ForceName('OutStringSize').AsInt64 := Length(OutStrings.Text); if Info.ForceName('OutStringSize').AsInt64 <= 10240 then Info.ForceName('OutStringS').AsString := OutStrings.Text; end; IsExecEnd := True; end; Info.ForceName('ExecEnd').AsBoolean := IsExecEnd; if not ProcessAppMessage then PostQuitMessage(ExitCode); end; end;
----------------------------------------------
delphi界写python最强, python界写delphi最强. 写自己的代码, 让别人去运行.