我有一个过程来捕获隐藏的命令提示符窗口并在TMemo
中显示输出。这是相同/相似的代码,张贴在互联网上和堆栈溢出:
var
Form1: TForm1;
commandline,workdir:string;
implementation
{$R *.dfm}
procedure GetDosOutput;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
StdOutPipeRead, StdOutPipeWrite: THandle;
WasOK: Boolean;
Buffer: array[0..255000] of AnsiChar;
BytesRead: Cardinal;
Handle: Boolean;
thisline,tmpline,lastline:string;
commandstartms:int64;
p1,p2:integer;
begin
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;
wShowWindow := SW_HIDE;
hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
hStdOutput := StdOutPipeWrite;
hStdError := StdOutPipeWrite;
end;
lastline:='';
Handle := CreateProcess(nil, PWideChar('cmd.exe /C ' + CommandLine),
nil, nil, True, 0, nil,
PWideChar(WorkDir), SI, PI);
CloseHandle(StdOutPipeWrite);
if Handle then
try
repeat
WasOK := ReadFile(StdOutPipeRead, Buffer, 255000, BytesRead, nil);
if BytesRead>0 then
begin
Buffer[BytesRead]:=#0;
Form1.CommandMemo.Lines.BeginUpdate;
thisline:=string(buffer);
Form1.CommandMemo.text:=Form1.CommandMemo.text+thisline;
//auto-scroll to end of memo
SendMessage(Form1.CommandMemo.Handle, EM_LINESCROLL, 0,Form1.CommandMemo.Lines.Count-1);
Form1.CommandMemo.Lines.EndUpdate;
end;
until not WasOK or (BytesRead = 0);
finally
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
end;
finally
CloseHandle(StdOutPipeRead);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
commandline:='tree c:';
workdir:='c:\';
GetDosOutput;
end;
它对任何ASCII输出都能正常工作,但不支持Unicode字符。
当tree
命令运行时,它通常显示如下字符:
│ │ │ │ │ ├───
...但备忘录显示:
³ ³ ³ ÃÄÄÄ
我尝试将缓冲区从AnsiChar
更改为Char
,这确实会在备忘录中显示Unicode,但这些只是损坏的Unicode字符,而不是命令行显示的内容:
††††‱楦敬猨
潭敶††††‱楦敬猨
潭敶䕈䑁椠潮⁷瑡〠捣攰ㅥ敍杲異汬爠煥敵瑳⌠㤷㔴映潲ⵥ⽷楦浩条ⵥ潤湷捳污汁敲摡⁹灵琠慤整ਮㅥ敍杲異汬爠煥敵††††‱楦敬猨
潭敶††††‱楦敬猨
潭敶ⵥ⽷楦浩条ⵥ潤湷捳污
有人能帮忙调整代码来支持命令行使用Unicode字符的时候吗?我已经花了几个小时的时间来尝试下面的建议,但是没有一个能在备忘录中正确显示树输出。有人能在这里修复我的示例代码或者发布适用于D11的代码吗?
1条答案
按热度按时间fivyi3re1#
我在Windows 7中使用 Delphi 7时可以使用它,输出如下:
我的主要区别是:
Widestring
和PWideChar
。现在的Delphi版本默认为Unicode,因此这将是String
和PChar
W
结尾)。cmd.exe /U
是因为根据它的手册要启用Unicode管道。WideChar
的缓冲区,而不是只把它放在字节(AnsiChar
)中。对于现在的 Delphi 版本,你应该简单地把它声明为Char
。很可能这是你的错。但是,如果your Windows system's default codepage或your process被设置为在API调用中总是使用UTF-8,那么您必须使用
TRUE
而不是FALSE
作为第三个参数来调用我的函数-这就是为什么我必须首先检查活动代码页(ACP)。DOS从未在Windows NT中存在过,the "black" window is not DOS。