Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么应用程序是';未显示的输出?_C#_.net - Fatal编程技术网

C# 为什么应用程序是';未显示的输出?

C# 为什么应用程序是';未显示的输出?,c#,.net,C#,.net,我有一个应用程序,它有以下Main: static void Main(string[] args) { Console.WriteLine("started"); if (args.Length == 0) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Applicatio

我有一个应用程序,它有以下
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
生成的任何输出。这是为什么?

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

因为:

这是因为启动WinForms的控制台窗口 应用程序属于cmd.exe进程,它与 您的WinForms应用程序进程


我发现它也提供了一些解决方法,我想我发现了问题,如果我错了,请原谅。
当您创建GUI应用程序并从控制台窗口运行它时,其标准输出流不会发送到以前打开的控制台窗口,因此不会显示。

但是如果你试着运行
yourexe.exe>test.txt
,你可以看到你用
Console.WriteLine编写的所有东西

摘录:

你不能,但你可以试着假装

[……]

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

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

Windows强制您在编译时做出决定:此应用程序将使用控制台(在这种情况下,它总是有一个控制台窗口,如果从图标或“开始”菜单启动,则会打开一个新窗口),还是不使用控制台(在这种情况下,它无法将输入或输出定向到启动它的控制台窗口——但是它可以)。如果您希望始终拥有控制台,请将构建类型更改为“控制台应用程序”;如果您不想拥有控制台,请将其保留为“Windows应用程序”

Raymond在文章中提到的巧妙变通方法是devenv(Visual Studio)和ildasm,以防链接崩溃:

在VisualStudio中,实际上有两个二进制文件:devenv.com和devenv.exe。devenv.com是一个控制台应用程序。devenv.exe是一个GUI应用程序。当您键入devenv时,由于Win32探测规则,会执行devenv.com。如果没有输入,devenv.com将启动devenv.exe并自行退出。如果有输入,devenv.com将按正常方式处理它们nsole应用程序

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


您似乎希望在控制台模式和GUI模式下运行应用程序。本例就是这样做的。基本上,您可以创建一个表单应用程序,如果从资源管理器运行,则可以有条件地在主应用程序中调用
alloconsole
。如果从命令提示符运行,则必须通过查看父进程来检测该命令提示符,您可以附加到它的co使用
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());
            }
        }
    }
    

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

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

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

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


如果你的应用类型不是“控制台”,我想你看不到用
控制台发送的输出消息。WriteLine
如果你在Visual Studio中调试,我想你会看到。@RichardEv:是的,在“输出”窗口中,我从命令行运行生成的可执行文件。你的项目的“输出类型”是什么设置为?OP时,希望应用程序在带参数运行时充当控制台,在不带参数运行时充当GUI。有趣的是,
yourexe.exe>test.txt
获取output@Tempus:嗯,
告诉console将标准输出重定向到文件…并且
console
类在标准输出上写入;)是的,我理解:)。我不知道运行GUI应用程序的中间命令提示符。我发现它的输出被发送到下一个命令提示符是很有趣的。这很有趣,但这会打开一个不同的命令提示符。不可能在同一个命令提示符中显示输出吗?这是一个或另一个,而不是两个。第一个是使用控制台而不使用表单,第二个是释放控制台并使用表单。我试图弄清楚如何让应用程序在传递参数时充当控制台应用程序,或者在其他情况下充当GUI应用程序,使用与C#完全不同的语言。但是,通过搜索,我找到了这个答案,它优雅地解决了我的问题。
 [DllImport("kernel32.dll", SetLastError = true)]
    public static extern int FreeConsole();