【问题标题】:Read Unicode/ANSI from Console从控制台读取 Unicode/ANSI
【发布时间】:2012-06-13 23:16:22
【问题描述】:

我用它从 cmd (Windows Shell) 中读取一个宽字符串。

var
 pBuffer       : array [0..250] of WideChar;
 aBuffer       : array [0..250] of Char;
 RealUnicode   : Integer;
 ExtendedAscii : Integer;
begin
 RealUnicode   := 2;
 ExtendedAscii := 1;
 // ... pipes etc...
 CreateProcessW(nil, pwidechar(ComSpec + ' /U'), nil, nil, TRUE, (CREATE_NEW_CONSOLE or CREATE_BREAKAWAY_FROM_JOB), nil, nil, StartupInfo, ProcessInfo);
 // ...
 while true do begin
  sleep (10); // Reduce CPU Usage
  GetExitCodeProcess(ProcessInfo.hProcess, ExitCode);
  if ExitCode <> STILL_ACTIVE then Break;
  FillChar(pBuffer,SizeOf(PBuffer), #0);
  ReadFile(hoRead, pBuffer[0], 250, BytesRead, nil);    
  if BytesRead > 0 then begin
   if (IsTextUnicode(@pBuffer, BytesRead, @RealUNICODE) or IsTextUnicode(@pBuffer, BytesRead, @ExtendedAscii) then begin
    MessagBoxW(0,dbuffer,'',0);
   end else begin
    FillChar    (aBuffer,SizeOf(aBuffer ), #0);
    CopyMemory  (@aBuffer , @pBuffer, BytesRead * 2);
    MessageBoxA (0, aBuffer, '', 0);
   end;
  end;
 end;
end;

这个sn-p 确实很好用。它确保如果 ansi 字符串/字符被写入控制台(例如 - ping.exe),它会在稍后获得 ANSI 输出。 不幸的是,有一个小故障。我使用 ping.exe,它可以正常工作,直到它返回到 Unicode 部分。这实际上很难解释,但我希望你们知道我的意思。 感谢您的帮助。

编辑: 当 ping.exe 完成后,sn-p 出于某种原因返回空字符串。尽管 readbytes > 0

编辑2:

说明: 我用 CreateProcesW 启动了 cmd,设置了管道等,然后读取了第一个缓冲区字节(Unicode 格式)。然后我输入 ipconfig 并切换回 ANSI。然后它读取字节,它们是空的 ANSI 字符串。之后,“程序”(不是 cmd)有时会崩溃。

编辑3: 我在这里有一个例子(带有源代码和二进制文件)。它是用delphi7和tntcontrols编译的。如果您没有 tntcontrols,只需在表单中添加一个备忘录(名称:Memo1)。并将宽字符串更改为字符串和/或尝试使用 messageboxW 对其进行调试。 http://dl.dropbox.com/u/349314/UNICODE%20Shell%20Example.rar 这个例子不关心 ansi 输入!

【问题讨论】:

  • 你有没有机会用一个能说明你意思的五行小程序替换ping.exe
  • 喜欢ipconfig?我发个截图
  • 屏幕截图可能会有所帮助,但我在想,你能不能写一个程序来执行printf("Hello\n"); 并显示它可以工作但printf("こんにちは\n"); 失败?或者其他一些明显的 Unicode 与 ANSI 输出问题......你能把它提炼成几个显示问题的特殊字符吗?
  • 不用担心在 UNICODE 中写入输出(我通常使用 TNTControls 来显示 WideStrings)。我的屏幕截图只显示了读取的内容和未读取的内容。

标签: delphi unicode cmd delphi-7


【解决方案1】:

控制台无法正确显示所有 Unicode 字符。这是因为控制台窗口限制。控制台进程的输出是 OEM 编码(或 DOS 编码),而不是 ANSI。

您可以通过将输出重定向到文件来检查它。通常,如果文件包含非英文字符,文件将无法在记事本中正确显示。

当您使用/u 运行cmd.exe 时,您可以预期它会将Unicode 字符写入管道。在这种情况下,您应该始终将输出视为 Unicode。


您通过调用 Wide-version 创建流程。但这并不意味着启动的进程使用 Unicode 函数来进行输出。此外,自 Windows 2000 起,所有 Ansi 版本的 Windows API 函数都是 Wide 版本的包装器:

  1. Ansi 函数使用默认代码页将输入参数中的所有文本转换为宽字符串。
  2. 然后它调用 Wide-version。
  3. 将结果(如果有)从 Wide- 转换为 Ansi 并返回。

但是,对于控制台窗口,情况并非如此。程序通常需要将其 Unicode 字符串转换为 OEM 编码(DOS 编码),然后将结果写入标准输出。只有在这种情况下,它才会被控制台窗口正确显示。

【讨论】:

    猜你喜欢
    • 2012-03-19
    • 1970-01-01
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多