为什么应用程序的输出未显示?

时间:2012-01-20 14:01:30

标签: c# .net

我有一个应用程序,它具有以下Main

static void Main(string[] args)
{
     Console.WriteLine("started");
     if (args.Length == 0)
     {
          Application.EnableVisualStyles();
          Application.SetCompatibleTextRenderingDefault(false);
          Application.Run(new Form1());
     }
     else
     {
          File.WriteAllText("./file.txt", "hello");
     }
}

我希望它支持从命令行运行,在某些脚本中使用,以及像GUI应用程序一样运行。但是,如果我从命令行运行它,并传递一个参数,我可以看到文件被创建,但我没有看到Console.WriteLine产生的任何输出。那是为什么?

6 个答案:

答案 0 :(得分:3)

我想我发现了问题,如果我错了,请原谅我 当您创建GUI应用程序并从控制台窗口运行它时,其标准输出流不会发送到先前打开的控制台窗口,因此它不会显示。
但是,如果您尝试运行yourexe.exe > test.txt,则可以看到您使用Console.WriteLine

撰写的所有内容

答案 1 :(得分:2)

它不会起作用因为:

  

那是因为启动WinForms的控制台窗口   应用程序属于cmd.exe进程,它独立于   你的WinForms申请流程。

我在this article中找到了这个,这也为AttachConsole Win32 method提供了一些解决方法

答案 2 :(得分:2)

您似乎希望在控制台模式和GUI模式下运行应用程序。这个例子做到了。基本上,您创建一个Form应用程序,如果从资源管理器运行,则在Main中有条件地调用AllocConsole。如果从命令提示符运行,您必须通过查看父进程来检测,您可以使用AttachConsole将其附加到其控制台。在这里,我对值进行了硬编码,但你可以查看参数并决定做任何事情。

基本上这个应用程序有三种模式

    如果从命令提示符启动,将使用父控制台的
  • bParentConsoleMode
  • bUsingOwnConsole如果在资源管理器中双击,则必须创建新的控制台
  • 最后,当上述两种情况都不正确时,它将作为常规表单应用程序运行。

    static class Program
    {
        [DllImport("kernel32.dll")]
        static extern bool AttachConsole(int dwProcessId);
        private const int ATTACH_PARENT_PROCESS = -1;
    
    
        [DllImport("kernel32.dll")]
        private static extern bool AllocConsole(); 
    
         [STAThread]
        static void Main()
        {
            bool bParentConsoleMode = true;
            bool bUsingOwnConsole = true;
            if (bParentConsoleMode)
            {
               AttachConsole(ATTACH_PARENT_PROCESS);
                Console.WriteLine("Using parent console");
                Console.ReadLine();
    
            }
            else if (bUsingOwnConsole)
            {
                AllocConsole();
                Console.WriteLine("Using own console");
                Console.ReadLine();
            }
            else //gui mode
            {
                Console.WriteLine("This is cool");
    
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }
    }
    

答案 3 :(得分:1)

请参阅Raymond Chen的这篇文章:How do I write a program that can be run either as a console or a GUI application?

摘录:

  

你不能,但你可以试着伪造它。

     

[...]

     

有些人想写我称之为“机会主义”的控制台程序。这些程序将使用其父级控制台(如果可用),但如果不是,则不希望为其创建控制台。内核不支持这种类型的程序,但这并没有阻止某些人提出clever workarounds

问题在于“决定”附加到现有控制台窗口以进行输入和输出,还是作为无控制台GUI应用程序运行?“在流程实际开始之前发生。您无法编写基于命令行参数做出决定的代码。

Windows迫使您在编译时做出决定:这个应用程序是否会使用控制台(在这种情况下,总是有一个控制台窗口,如果它被启动则会打开一个新的控制台窗口从一个图标或开始菜单),或者它不会使用控制台(在这种情况下它不能直接输入或输出它从它启动的控制台窗口 - 但它可以, create a new console window)。如果您想要始终拥有控制台,请将您的构建类型更改为“控制台应用程序”;如果你想永远不要有控制台,请把它留作“Windows应用程序”。

雷蒙德的文章中提到的聪明的解决方法,如果链接腐烂,是devenv(Visual Studio)和ildasm:

  

在VisualStudio案例中,实际上有两个二进制文件:devenv.com和devenv.exe。 Devenv.com是一款控制台应用。 Devenv.exe是一个GUI应用程序。当您键入devenv时,由于Win32探测规则,会执行devenv.com。如果没有输入,devenv.com将启动devenv.exe,并退出。如果有输入,devenv.com会将它们作为普通的控制台应用程序处理。

     

在ildasm案例中,只有一个二进制文件:ildasm.exe。它首先被编译为GUI应用程序。稍后editbin.exe用于将其标记为控制台子系统。在其主要方法中,它确定是否需要以控制台模式或GUI模式运行。如果需要以GUI模式运行,它会将自身重新启动为GUI应用程序。

答案 4 :(得分:0)

正如Marco指出的那样,您是否尝试将应用程序的输出类型设置为“控制台应用程序”?

答案 5 :(得分:0)

我使用以下代码执行类似的操作:

 Console.WriteLine("started");
 if (args.Length == 0)
 {
     ProcessForConsole(argsParser);
 }
 else
 {
     NativeMethods.FreeConsole();
     Application.EnableVisualStyles();
     Application.SetCompatibleTextRenderingDefault(false);
     Application.Run(new Form1());                
 }    

。 。 。

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

将主应用程序设置为控制台应用程序,然后将FreeConsole设置为分离它。

  

进程可以使用FreeConsole函数将自己从控制台中分离出来。如果其他进程共享控制台,则不会销毁控制台,但调用FreeConsole的进程无法引用它。当连接到它的最后一个进程终止或调用FreeConsole时,控制台将关闭。

来自microsoft.