如何在Delphi 2009重定向控制台(stin,sterr)? [英] How in Delphi 2009 redirect console (stin, sterr)?

查看:152
本文介绍了如何在Delphi 2009重定向控制台(stin,sterr)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在互联网上尝试了几个样本,没有一个工作 - 脚本没有执行 - (可能是因为是为了Delphi 2009的unicode?)。



I需要运行一些python脚本并传递参数给他们,如:

  python.. \Plugins\RunPlugin.py -a login -u Test -p test 

并将输出捕获到字符串&



这是我现在所在:

 程序RunDosInMemo(DosApp:String; var OutData:String); 
var
SA:TSecurityAttributes;
SI:TStartupInfo;
PI:TProcessInformation;
StdOutPipeRead,StdOutPipeWrite:THandle;
WasOK:Boolean;
缓冲区:数组[0..255]的Char;
BytesRead:Cardinal;
WorkDir:string;
句柄:布尔值
begin
OutData:='';
with SA do begin
nLength:= SizeOf(SA);
bInheritHandle:= True;
lpSecurityDescriptor:= nil;
结束
CreatePipe(StdOutPipeRead,StdOutPipeWrite,@SA,0);
尝试
与SI do
begin
FillChar(SI,SizeOf(SI),0);
cb:= SizeOf(SI);
dwFlags:= STARTF_USESHOWWINDOW或STARTF_USESTDHANDLES或CREATE_UNICODE_ENVIRONON;
wShowWindow:= SW_HIDE;
hStdInput:= GetStdHandle(STD_INPUT_HANDLE); //不要重定向stdin
hStdOutput:= StdOutPipeWrite;
hStdError:= StdOutPipeWrite;
结束
WorkDir:='C:\';
句柄:= CreateProcess(nil,PChar(DosApp),
nil,nil,True,0,nil,
PChar(WorkDir),SI,PI);
CloseHandle(StdOutPipeWrite);
如果Handle然后
开始
尝试
重复
WasOK:= ReadFile(StdOutPipeRead,Buffer,255,BytesRead,nil);
if BytesRead> 0然后
begin
缓冲区[BytesRead]:=#0;
OutData:= OutData + String(Buffer);
结束
直到不是WasOK或(BytesRead = 0);
WaitForSingleObject(PI.hProcess,INFINITE);
finally
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
结束
end else begin
raise Exception.Create('Failed to load python plugin');
结束
finally
CloseHandle(StdOutPipeRead);
结束
结束


解决方案

我不确定WaitForSingleObject是去...我认为最好用GetExitCodeProcess(pi.hProcess,iExitCode)循环,直到iExitCode<> STILL_ACTIVE,然后检查循环中每次传递的数据。



编写的代码在Delphi 2007中也不运行,所以它不是Delphi 2009 unicode问题。



将内部循环更改为以下工作:

 如果Handle然后
开始
尝试
repeat
WasOK:= ReadFile(StdOutPipeRead,Buffer,255,BytesRead,nil);
for ix:= 0 to BytesRead-1 do
begin
OutData:= OutData + AnsiChar(Buffer [ix]);
结束
GetExitCodeProcess(pi.hProcess,iExit);
until(iExit<> STILL_ACTIVE);
finally
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
结束

我对本地变量进行了以下更正/添加:

 缓冲区:字节数组[0..255] 
iExit:红衣主教;
IX:整数;

我还在StdOutPipeRead关闭之前移动了CloseHandle(StdOutPipeWrite)。


I try several samples in the internet and none of them work - the scripts are not executed- (maybe because are for pre Delphi 2009 unicode?).

I need to run some python scripts and pass arguments to them, like:

python "..\Plugins\RunPlugin.py" -a login -u Test -p test

And capture the output to a string & the errors to other.

This is what I have now:

procedure RunDosInMemo(DosApp:String; var OutData: String);
var
  SA: TSecurityAttributes;
  SI: TStartupInfo;
  PI: TProcessInformation;
  StdOutPipeRead, StdOutPipeWrite: THandle;
  WasOK: Boolean;
  Buffer: array[0..255] of Char;
  BytesRead: Cardinal;
  WorkDir: string;
  Handle: Boolean;
begin
  OutData := '';
  with SA do begin
    nLength := SizeOf(SA);
    bInheritHandle := True;
    lpSecurityDescriptor := nil;
  end;
  CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
  try
    with SI do
    begin
      FillChar(SI, SizeOf(SI), 0);
      cb := SizeOf(SI);
      dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES or CREATE_UNICODE_ENVIRONMENT;
      wShowWindow := SW_HIDE;
      hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
      hStdOutput := StdOutPipeWrite;
      hStdError := StdOutPipeWrite;
    end;
    WorkDir := 'C:\';
    Handle := CreateProcess(nil, PChar(DosApp),
                            nil, nil, True, 0, nil,
                            PChar(WorkDir), SI, PI);
    CloseHandle(StdOutPipeWrite);
    if Handle then
    begin
      try
        repeat
          WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
          if BytesRead > 0 then
          begin
            Buffer[BytesRead] := #0;
            OutData := OutData + String(Buffer);
          end;
        until not WasOK or (BytesRead = 0);
        WaitForSingleObject(PI.hProcess, INFINITE);
      finally
        CloseHandle(PI.hThread);
        CloseHandle(PI.hProcess);
      end;
    end else begin
      raise Exception.Create('Failed to load python plugin');
    end;
  finally
    CloseHandle(StdOutPipeRead);
  end;
end;

解决方案

I'm not certain the WaitForSingleObject is the way to go... I think its better to loop with GetExitCodeProcess(pi.hProcess,iExitCode) until iExitCode <> STILL_ACTIVE and then check for data on each pass through the loop.

The code as written does not operate under Delphi 2007 either, so its not a Delphi 2009 unicode issue.

Changing your inner loop to the following works:

if Handle then
begin
  try
    repeat
      WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
      for ix := 0 to BytesRead-1 do
        begin
          OutData := OutData + AnsiChar(Buffer[ix]);
        end;
      GetExitCodeProcess(pi.hProcess,iExit);
    until (iExit <> STILL_ACTIVE);
  finally
    CloseHandle(PI.hThread);
    CloseHandle(PI.hProcess);
  end;

I made the following corrections/additions to the local variables:

Buffer: array[0..255] of byte;
iExit : Cardinal;
IX : integer;

I also moved the CloseHandle(StdOutPipeWrite) just before the close of the StdOutPipeRead.

这篇关于如何在Delphi 2009重定向控制台(stin,sterr)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆