Console.Writeline()不起作用

8

我正在创建一个C# WinForms项目,可以作为GUI运行,也可以从命令行操作。目前,我可以处理命令行输入和参数。我可以从命令行运行程序,并且可以使用程序来处理参数。但是Console.Writeline()没有任何反应。有什么线索吗?


3
请参见:https://dev59.com/IHRA5IYBdhLWcg3w1BqW。 - Thorarin
你的意思是在命令行模式下运行程序时,调用Console.WriteLine似乎会默默失败吗? - Adam Robinson
你可以试试下面这个简单的代码 -static void Main(string[] args) { foreach(string arg in args) { Console.WriteLine(arg); } Console.ReadLine(); }能正常运行吗? - Mutant
谢谢Thorarin,这可能正是我要找的。所以我猜尽管命令行可以运行我的GUI应用程序...但为了编写或与其交互,我必须创建一个新的命令行并附加它?这正确吗? - novacara
对其他人: 我需要程序能够以GUI或命令行方式运行。因此在这种情况下更改项目设置是无济于事的。 - novacara
可能是Console.WriteLine在输出窗口中没有显示的重复问题。 - nawfal
7个回答

7

大部分内容请参考这里的回答。不过,我想指出FreeConsole()API调用的存在,它可以让你优雅地关闭控制台。

[DllImport("kernel32.dll")]
static extern int FreeConsole() 

需要翻译的内容如下:

需要注意的一件事情是:如果您从现有控制台启动并使用AttachConsole附加到该控制台(而不是使用AllocConsole),则可能会看到命令提示符出现在控制台输出前面。

这是一个难以解决的时间问题。如果这是个问题,请按照其他人建议的设置应用程序为控制台应用程序。这将产生没有命令提示符出现的效果,直到应用程序关闭,但如果您正在打开窗体,则可能不是您想要的。

针对您的评论:它要么是AttachConsole 或者 AllocConsole。我链接的示例首先尝试附加到现有控制台。如果失败(最可能是因为不存在),则创建一个新的控制台窗口。

如果您找到了同时具有命令行行为和GUI交互模式的最佳方法,请告诉我。我没有进行任何深入搜索解决方案,但我有几个小型应用程序可以受益。

顺便说一句:如果您计划在命令行上使用管道(例如将输出重定向到文件),那么很遗憾,这种方法不起作用。


这个解决方案很棒。幸运的是我不需要管道。谢谢!! - novacara

7

您可以使用以下 DllImports 在 Windows Forms 应用程序中启用控制台:

    [DllImport("kernel32.dll")]
    static extern bool AttachConsole(int dwProcessId);
    private const int ATTACH_PARENT_PROCESS = -1;

    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern int FreeConsole();

您可以使用以下命令启用控制台:

    AttachConsole(ATTACH_PARENT_PROCESS);

您可以通过以下方式禁用它:

     FreeConsole();

3

我在后台线程中执行了一个从动态加载的DLL(反射)中运行函数的操作。

AllocConsole();
IntPtr stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);

StreamWriter standardOutput = new StreamWriter(Console.OpenStandardOutput());
standardOutput.AutoFlush = true;
Console.SetOut(standardOutput);
//
//Console writing here
//
FreeConsole();

在我添加了Console.SetOut()之前,我的控制台一片空白。我不确定您是否需要调用GetStdHandle()。


谢谢,我曾经有一个AllocConsole一直在工作,但突然间就不行了。加上Console.SetOut()就解决了问题! - Emile Vrijdags
哇,有很多关于如何解决这个问题的答案。在我查看了之前的十几个答案之后,你的方法起作用了。我正在使用kernel32的"attachconsole"。需要新的streamwriter,自动刷新为true,并且设置输出。 - DAG

3
这是因为您编写了一个winforms应用程序 - 这意味着System.Console.Out(即标准输出流)设置为Stream.Null。这意味着对该流的任何调用都会悄无声息地失败。
您可以从命令行处理输入,因为它们来自不同的流。故事的寓意是您可以拥有winforms应用程序或命令行应用程序,但不能同时拥有两者。

是的,有点类似... Windows API调用来了解救 :) - Thorarin
1
这个答案应该被删除,因为它有不准确的陈述:“故事的寓意是你可以拥有一个WinForms应用程序或一个命令行应用程序,但不能同时拥有两者。”gls123已经证明了它是错误的。 - HerrimanCoder

1

您可能需要更改应用程序类型。可以通过在GUI中的应用程序属性中更改(如ConsultUtah的answer所述),也可以通过编辑.csproj文件来完成:

Winform/WPF:

<OutputType>WinExe</OutputType>

控制台(这是让console.writeline()正常工作所需的内容):

<OutputType>Exe</OutputType>

Dll(包括Web应用程序):
<OutputType>Library</OutputType>

0

这与您在项目属性的App选项卡上配置的项目类型有关,您有3个选项:

  • 控制台应用程序
  • Win应用程序
  • 类库

如果您使用Win应用程序,则还可以处理命令行参数,因为这些参数是在Main函数中接收的。


0
该项目必须设置为编译为控制台应用程序,以使控制台函数正常工作。另一方面,即使作为 GUI 运行,它也将始终拥有控制台窗口。我不知道有没有解决这个问题的方法(但如果有的话,我会很感兴趣听听)。

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