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

标签 delphi console cmd pipe command-line-arguments

如何让 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, @Security, 0);
    CreatePipe(ErrorPipeRead, ErrorPipeWrite, @Security, 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), @Security, @Security, true,
               CREATE_NEW_CONSOLE or SYNCHRONIZE, // CREATE_NO_WINDOW,
               nil, 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, nil, 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], Length(InString),... 您应该编写如下内容:

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

关于delphi - Delphi 中用于命令提示符的管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16225025/

相关文章:

scala - 有没有一种快速的方法来显示在 Scala 控制台中声明的方法的代码?

linux - UART 绑定(bind)@运行时

windows - 如何在 Windows 命令提示符批处理文件中使用嵌套 FOR 内的 SET/A 来增加数值?

delphi - 如何在 QuickReports 中实现可变高度细节带

android - 加载 jbitmap 数据

c - 如何将c中的数据类型byte []转换为delphi?

node.js - winston.debug 在终端上不显示任何内容

batch-file - 在 UNC 路径上运行 Get-ChildItem 在 Powershell 中有效,但在批处理文件中运行的 Powershell 中无效

windows - 使用 SC 安装 Windows 服务

delphi - 如何判断 Delphi 应用程序 "owns"是否是其控制台?