在分配控制台之前调用Console.WriteLine()函数

7

我最近在我的应用程序中遇到了以下问题:尽管已经使用 AllocConsole 分配了控制台,但它没有显示任何控制台输出。很快我就发现,这是由于在调用 AllocConsole 之前(隐藏得很深)尝试向控制台写入所致。因此,情况看起来像这样:

Console.WriteLine("Foo"); // no console allocated yet
AllocConsole();           // console window appears
Console.WriteLine("Bar"); // expecting "Bar" in the console, but the console is blank

所以我的问题是:为什么会发生这种情况?我没有看到任何异常(虽然我认为它们可能存在)。

既然已经解释了它发生的原因,我希望有人能解释一下该怎么做才能解决它。任何第三方库都可以写入控制台并破坏其他所有人的事情吗?正确的解决方案只是在执行任何其他操作之前尽早决定并“AllocConsole”吗? - Miserable Variable
@Hemal 我使用了Rick描述的方法 - 在AllocConsole之后调用Console.OpenStandardOutput()。这样我就可以确保至少在AllocConsole之后写入的所有输出都会显示出来。 - Dmitrii Erokhin
3个回答

12
第一次使用 Console.WriteLine 时,Console 类会创建一个 TextWriter 并将其与 Console.Out 属性关联。它的实现方式是使用 Win32 打开与标准输出文件句柄相关联的低级文件句柄。如果标准输出句柄无效,则 Console.Out 设置为TextWriter.Null,它会丢弃所有输出。

Win32 的 AllocConsole 函数创建并设置标准输出句柄,因此在调用它之后,标准输出句柄将不同或现在有效。在任何情况下,Console.Out 已经被设置为使用旧的标准输出或丢弃所有输出。

如果要在调用 AllocConsole 后强制重新打开 Console.Out,可以使用此方法:


哇,如果其他人看到这个消息,似乎这可能是竞争条件的问题 - 分配,然后写入控制台却得不到任何反应。而且,我还必须编写Console.SetOut(new StreamWriter(Console.OpenStandardOutput())),仅调用Console.OpenStandardOutput()是没有帮助的。 - MatthewMartin

1
可能是因为Console类的静态构造函数在第一次调用Console.WriteLine时设置了输出流。由于没有连接控制台,因此没有标准输出句柄,输出被路由到位桶。当您稍后调用AllocConsole时,Console类中的任何内容都不会被通知现在存在一个控制台。它没有机会将Console.Out附加到新创建的标准输出句柄上。

0
一个进程只能关联一个控制台,因此如果调用进程已经有控制台,则 AllocConsole 函数将失败。而且该控制台应用程序已经拥有控制台。详见 这里

我的应用程序被编译为GUI应用程序,但在使用命令行参数运行时它会使用控制台。 - Dmitrii Erokhin
你怎么知道这是一个控制台应用程序?它很可能是一个带有控制台的Windows应用程序。编辑:告诉你了。 - BoltClock
Console.WriteLine在AllocConsole之前被写入,所以我以为它是。不管怎样,对此我表示歉意 :) 在这种情况下,GetLastError()可能会告诉你一些信息 - Ujjwal Manandhar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接