为什么在重定向输出时调整控制台缓冲区会引发无效句柄异常?

Why does adjusting console buffer raise invalid handle exception when redirecting output?

在 C# 控制台应用程序中调整 Console.BufferWidth 会在将输出重定向到文件时引发异常。让我们调用示例 test1.exe:

static void Main(string[] args) {
    Console.BufferWidth = 240;
    Console.WriteLine("output1\noutput2");
}

标准输出没问题:

test1.exe
output1
output2

重定向到文件引发异常:

test1.exe > file.txt

Unhandled Exception: System.IO.IOException: The handle is invalid.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.__Error.WinIOError()
   at System.Console.SetBufferSize(Int32 width, Int32 height)
   at System.Console.set_BufferWidth(Int32 value)
   at test1.Program.Main(String[] args) in \wopr\falken\test1\Program.cs:line 13

忽略使用 try...catch 很容易,但是对于文件句柄或一般的句柄,我有一些不了解的地方。

为什么句柄无效?

重定向到文件

test1.exe > file.txt

意味着操作系统正在将您的应用程序的输出流从标准输出流(控制台)重定向到一个文件,这发生在进程启动时。

控制台和文件都称为“I/O 设备”,操作系统为它们各自分配了一个名为“handle”的唯一 ID 号”。系统使用此句柄来跟踪设备的属性。

不同的设备有不同的属性。控制台在视觉上由其 window 表示,但数据(字符)存储在其缓冲区中。 Window 有其宽度和高度(参见 Console.WindowWidth and Console.WindowHeight properties) but also screen buffer size - Width and Height (see Console.BufferWidth and Console.BufferHeight 属性)。如果打开 命令提示符 并转到 drop-down 菜单中的 属性 ,您可以手动编辑这些属性,如果您单击该图标,就会出现该菜单在标题栏的左上角。

当您的应用程序执行时

Console.BufferWidth = 240;

它尝试更改当前输出设备(文件)不存在的属性(window 缓冲区大小)。您的应用程序已重定向输出,它有一个文件句柄,并且 Console.BufferWidth 在 object 上不受支持。因此你得到 IOException (句柄无效)。

关于 Console Class 如何在重定向情况下设计代码的 MSDN 页面:

Console class members that work normally when the underlying stream is directed to a console might throw an exception if the stream is redirected, for example, to a file. Program your application to catch System.IO.IOException exceptions if you redirect a standard stream. You can also use the IsOutputRedirected, IsInputRedirected, and IsErrorRedirected properties to determine whether a standard stream is redirected before performing an operation that throws an System.IO.IOException exception.