加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Delphi中的管道用于命令提示符

发布时间:2020-12-15 09:28:33 所属栏目:大数据 来源:网络整理
导读:如何让Delphi将字符串传递给CMD进程的输入管道.我能够得到一个错误管道和输出管道正常运行,不幸的是不是输入管道.我正在使用的代码取自管道的在线教程.原始代码中有几个错误在编译时导致问题.它们已被修复,但在尝试传递输入时仍然存在问题. 这是Form.Create
如何让Delphi将字符串传递给CMD进程的输入管道.我能够得到一个错误管道和输出管道正常运行,不幸的是不是输入管道.我正在使用的代码取自管道的在线教程.原始代码中有几个错误在编译时导致问题.它们已被修复,但在尝试传递输入时仍然存在问题.

这是Form.Create事件中的代码.我还包括WritePipe和ReadPipe方法. WritePipe不起作用,ReadPipe确实有效. Pipe方法中的WriteFile和ReadFile都返回一条成功的消息,但只有ReadPipe才能正常工作.

var
    DosApp: String;
    DosSize: Integer;
    Security : TSecurityAttributes;
    start : TStartUpInfo;
    byteswritten: DWord;
    WriteString : ansistring;
  begin
    CommandText.Clear;
    // get COMSPEC variable,this is the path of the command-interpreter
    SetLength(Dosapp,255);
    DosSize := GetEnvironmentVariable('COMSPEC',@DosApp[1],255);
    SetLength(Dosapp,DosSize);

  // create pipes
    With Security do
      begin
        nlength := SizeOf(TSecurityAttributes) ;
        binherithandle := true;
        lpsecuritydescriptor := nil;
      end;

    CreatePipe(InputPipeRead,InputPipeWrite,@Security,0);
    CreatePipe(OutputPipeRead,OutputPipeWrite,0);
    CreatePipe(ErrorPipeRead,ErrorPipeWrite,0);

    // start command-interpreter
    FillChar(Start,Sizeof(Start),#0) ;

    //start.hStdInput := InputPipeRead;
    start.hStdOutput := OutputPipeWrite;
    start.hStdError :=  ErrorPipeWrite;

    start.dwFlags := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW;
    start.wShowWindow := SW_Show;//SW_HIDE;
    start.cb := SizeOf(start) ;

    if CreateProcess('',PChar(DosApp),true,CREATE_NEW_CONSOLE or SYNCHRONIZE,// CREATE_NO_WINDOW,nil,start,ProcessInfo) then
      begin
        MyThread := MainUnit.monitor.Create;  // start monitor thread
        MyThread.Priority := tpHigher;
      end;

    Button1.Enabled := true;
    cmdcount := 1;

end;

写管道:

procedure WritePipeOut(OutputPipe: THandle; InString: PWideChar);
// writes Instring to the pipe handle described by OutputPipe
  var
    count : integer;
    byteswritten: DWord;
    outputstring : PAnsiChar;
    TextBuffer: array[1..32767] of AnsiChar;// char;
    TextString: String;
  begin

// most console programs require CR/LF after their input.

    InString := PWideChar(InString + #13#10);

    WriteFile(InputPipeWrite,InString[1],Length(InString),byteswritten,nil);

  end;

读管:

function ReadPipeInput(InputPipe: THandle; var BytesRem: Integer): String;
  {
    reads console output from InputPipe.  Returns the input in function
    result.  Returns bytes of remaining information to BytesRem
  }
  var
    TextBuffer: array[1..32767] of AnsiChar;// char;
    TextString: String;
    BytesRead: Cardinal;
    PipeSize: Integer;
  begin
    Result := '';
    PipeSize := length(TextBuffer);
    // check if there is something to read in pipe
    PeekNamedPipe(InputPipe,PipeSize,@BytesRead,@PipeSize,@BytesRem);
    if bytesread > 0 then
      begin
        ReadFile(InputPipe,TextBuffer,pipesize,bytesread,nil);
        // a requirement for Windows OS system components
        OemToChar(@TextBuffer,@TextBuffer);
        TextString := String(TextBuffer);
        SetLength(TextString,BytesRead);
        Result := TextString;
      end;
  end;

进一步说明;这是为了与Java调试器一起使用,它需要分阶段输入,所以我不相信除了直接操作输入到JDB之外还有任何替代方法.

任何帮助深表感谢!

解决方法

1)您应该将InputPipeRead作为hStdInput传递给CreateProcess:取消注释你的行start.hStdInput:= InputPipeRead;

2)WritePipeOut函数有两个错误:它将Unicode(UTF-16LE)字符串写入管道,并跳过第一个字符(因为它写入一个以InString [1]开头的内存区域).而不是WriteFile(InputPipeWrite,InString [1],…你应该写如下:

var AnsiBuf: AnsiString;
...
  AnsiBuf := String(InString) + #13#10;
  Write(InputPipeWrite,AnsiBuf[1],Length(AnsiBuf),nil);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读