从 cmd 运行时控制台应用和窗体应用的区别

4

我有一个WinForms应用程序,有时会从命令行中使用。 以下是代码(当然是经过简化的):

[STAThread]
static void Main()
{
    AttachConsole(ATTACH_PARENT_PROCESS);
    Console.WriteLine("Hello");

    /*Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());*/
}

如果这是一个控制台应用程序,输出可能是:
C:\ConsoleApplication\ConsoleApplication.exe
Hello
C:\ConsoleApplication\_

在Windows应用程序中,实际上是这样的:
C:\WindowsApplication\WindowsApplication.exe
C:\WindowsApplication\Hello
_

有人能告诉我为什么会出现这样的区别,以及如何让我的Windows应用程序在从cmd运行时表现得像控制台吗?

编辑:

我希望我的Windows应用程序在从cmd运行时表现得像控制台。

C:\WindowsApplication\WindowsApplication.exe
Hello
C:\WindowsApplication\_

解决方案:

因此我正在以以下方式运行我的应用程序

C:\WindowsApplication\start /wait WindowsApplication.exe

2
你究竟想要实现什么目标? - Security Hound
可能有用:http://pinvoke.net/default.aspx/kernel32/AttachConsole.html - Matt
3个回答

10

是的。不同之处在于cmd.exe了解可执行文件的类型。它知道当应用程序是控制台模式时要等待进程终止。当应用程序是常规的Windows GUI应用程序时,它不会等待,信任其将创建自己的窗口。因此,它再次显示命令提示符,你的输出被追加到其中。顺便提一下,你也会遇到使用Console.ReadLine() 时的麻烦。

你需要使用start /wait yourapp.exe来强制cmd.exe等待启动程序。而调用AllocConsole()是唯一通用的解决方法。同时也负责在从快捷方式启动应用程序时创建控制台。

AllocConsole()相当令人迷惑。考虑编写一个微型控制台模式应用程序,只需执行Process.Start + WaitForExit以启动主程序,或许还可以混合命令行参数。这样就可以获得阻塞行为。如果将可执行文件重命名为mainapp.com(以启动mainapp.exe),则隐藏了区别,这也是VS使用的技巧(devenv.exe与 devenv.com)。


4
在exe中有一个标志,用于指示这是控制台应用程序还是GUI应用程序(在您的情况下为Winform)。当您启动应用程序时,如果它是控制台应用程序,Windows将从程序中分离控制台。您可以使用以下方法来实现您想要的效果:
  1. 将应用程序编译为GUI,命名为mytool.exe
  2. 创建一个doskey别名mytool=start /wait c:\path\mytool.exe $*
这样,当您在资源管理器或快捷方式中启动mytool.exe时,您将启动一个普通的Windows应用程序; 当您在控制台中键入mytool时,实际上您是通过"start /wait"启动它,无论标志如何都不会分离控制台。(但是,如果您想要从控制台输出/输入某些东西,则确实需要连接到父控制台。)

0

如果我理解正确,您想让Windows应用程序在运行时阻止控制台线程。我不知道为什么您要这样做,但我可以尝试说明它可能的工作方式:

将WinForms应用程序更改为控制台应用程序,打开一个窗体。这样它就会在显示窗口时阻止控制台线程。


我这样做是因为我已经有一个可以从cmd使用的应用程序(它可以从批处理文件中调用,然后在静默模式下工作)。但是我还必须支持帮助命令,当最后一行为空行时,它看起来不好。 - username

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