Delphi中用于命令提示符的管道 [英] Pipes in Delphi for Command Prompt
问题描述
如何使Delphi将字符串传递到CMD进程的输入管道.我能够得到一个错误管道,并且输出管道可以正常运行,但是不幸的是,输入管道却不能正常运行.我正在使用的代码取自用于管道的在线教程.原始代码中有几个错误,导致在编译时出现问题.它们已得到修复,但是在尝试仍然传递输入时,我仍然遇到问题.
How can I get Delphi to pass a string to the input pipe to a CMD process. I am able to get an error pipe and output pipe functioning properly, unfortunately not the input pipe. The code I am using is taken from an online tutorial for piping. There were several errors in the original code causing problems when it was compiled. They have been fixed but I am left with problems when trying to pass input still.
这是Form.Create事件中的代码.我还包括了WritePipe和ReadPipe方法. WritePipe不起作用,ReadPipe起作用. Pipe方法中的WriteFile和ReadFile都返回一条成功消息,但是只有ReadPipe实际上有效.
Here is the code in the Form.Create event. I also have included the WritePipe and ReadPipe methods. WritePipe does not work, ReadPipe does work. Both WriteFile and ReadFile in the Pipe methods return a successful message, only the ReadPipe actually works however.
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 Debugger一起使用的,它需要分阶段进行输入,因此我认为除了直接将输入操作到JDB之外,没有其他替代方法.
Further note; this is for use with the Java Debugger, which requires input in stages and so I do not believe there is any alternative method other than manipulating input directly to the JDB.
非常感谢您的帮助!
推荐答案
1)您应该将InputPipeRead作为hStdInput传递给CreateProcess
:取消注释行start.hStdInput := InputPipeRead;
1) You should pass InputPipeRead as hStdInput into CreateProcess
: uncomment your line start.hStdInput := InputPipeRead;
2)WritePipeOut
函数有两个错误:将Unicode(UTF-16LE)字符串写入管道,并且跳过第一个字符(因为它写入从InString [1]开始的内存区域).而不是WriteFile(InputPipeWrite, InString[1], Length(InString),...
,您应该编写如下内容:
2) The WritePipeOut
function has two errors: it writes a Unicode (UTF-16LE) string into a pipe, and it skips the first character (since it writes a memory area beginning at InString[1]). Instead of WriteFile(InputPipeWrite, InString[1], Length(InString),...
you should write something like:
var AnsiBuf: AnsiString;
...
AnsiBuf := String(InString) + #13#10;
Write(InputPipeWrite, AnsiBuf[1], Length(AnsiBuf), byteswritten, nil);
这篇关于Delphi中用于命令提示符的管道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!