.net - 是否可以构建双击时不显示控制台窗口的控制台应用程序?

标签 .net windows console console-application

Related:
Should I include a command line mode in my applications?
How to grab parent process standard output?
Can a console application detect if it has been run from Explorer?

我想构建一个通常从命令行运行的控制台应用程序。

但是,当它在资源管理器中双击时(而不是在 cmd.exe 提示符下运行),我希望程序不显示控制台窗口。

我想避免这种情况:

alt text

这可能吗?

编辑 我想另一种提问方式是,程序是否有可能知道它是如何被调用的——无论是通过双击还是通过命令行

我在 Windows 上使用 .NET 工作。

编辑 2: 来自 this Old New Thing blog post我学到了一些好东西。这是我现在所知道的...

在 Windows 中,EXE 文件被标记为 GUI 或非 GUI。对于 csc.exe,这是通过 /target:winexe/target:exe 选择的。在进程中的第一条指令执行之前,Windows 内核会设置执行环境。在那一刻,如果 EXE 被标记为 GUI,内核将进程的 stdin/stdout 设置为 NULL,如果非 GUI(命令行),内核将创建一个控制台并将进程的 stdin/stdout 设置为安慰。

启动进程时,如果没有stdin/stdout (== /target:winexe),则调用立即返回。因此,从 cmd.exe 启动 gui 应用程序,您将立即返回 cmd 提示符。如果有标准输入/标准输出,并且如果从 cmd.exe 运行,则父 cmd.exe 等待进程退出。

“立即返回”很重要,因为如果您编写一个 GUI 应用程序以附加到其父控制台,您将能够执行 console.writeline 等操作。但是 cmd.exe 提示符是事件的。用户可以键入新命令、启动新进程等。换句话说,从 winexe 中,简单地使用 AttachConsole(-1) 附加到父控制台不会将其“变成”控制台应用程序。


在这一点上,我认为允许应用程序在从 cmd.exe 调用时使用控制台,并且在双击时不使用它的唯一方法是将 exe 定义为常规控制台 exe ( /target:exe),并在启动时隐藏窗口(如果合适)。您仍然会看到一个控制台窗口短暂出现。

我仍然没有想出如何知道它是从资源管理器还是从 cmd.exe 启动的,但我越来越接近了..


答案

无法构建不显示控制台窗口的控制台应用程序。

有可能构建一个非常快速地隐藏其窗口的控制台应用程序,但不能快到窗口好像永远不会出现一样。

现在,要确定控制台应用程序是否是从资源管理器启动的,有些人建议查看它在其中运行的控制台
(来自 mgb's answerKB article 99115 ):

  int left = Console.CursorLeft;
  int top = Console.CursorTop;
  bool ProcessWasRunFromExplorer = (left==0 && top==0);

这会告诉您进程是否在其自己的控制台中启动,但不会告诉您它是否是资源管理器。在资源管理器中双击会执行此操作,但应用程序中的 Start.Process() 也会执行相同的操作。

如果您想区别对待这些情况,请使用它来了解父进程的名称:

  System.Console.WriteLine("Process id: {0}", Process.GetCurrentProcess().Id);
  string name = Process.GetCurrentProcess().ProcessName ;
  System.Console.WriteLine("Process name: {0}", name);
  PerformanceCounter pc = new PerformanceCounter("Process", "Creating Process Id", name);
  Process p = Process.GetProcessById((int)pc.RawValue);
  System.Console.WriteLine("Parent Process id: {0}", p.Id);
  System.Console.WriteLine("Parent Process name: {0}", p.ProcessName);

  // p.ProcessName == "cmd" or "Explorer" etc

要在进程启动后快速隐藏窗口,请使用:

  private static readonly int SW_HIDE= 0;

  [System.Runtime.InteropServices.DllImport("user32.dll")]
  private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);

  ....
  {
    IntPtr myHandle = Process.GetCurrentProcess().MainWindowHandle;
    ShowWindow(myHandle, SW_HIDE);
  }

如果您生成一个 winexe(一个 WinForms 应用程序),并在适当的时候使用 AttachConsole(-1) 选择性地附加到父控制台,您不会得到等效的一个常规的控制台应用程序。对于 winexe,父进程(如 cmd.exe)将在启动 GUI 应用程序后立即返回到命令提示符。换句话说,命令提示符处于事件状态并准备好输入,而刚刚启动的进程可能正在发出输出。这令人困惑,可能仅对调试 winforms 应用程序有用。

这对我有用。

最佳答案

只需将其构建为 Windows 窗体应用程序,但不要为其提供 GUI。不幸的是,当它从命令行运行时,您也不会得到任何控制台输出……这是个问题吗?

关于.net - 是否可以构建双击时不显示控制台窗口的控制台应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1528152/

相关文章:

python - 在 windows anaconda 中安装 tensorflow - 并使用 Spyder GUI 运行它

客户端的 java 客户端-服务器问题(无 System.out)

linux - 如何在 Linux 中将 cout 重定向到控制台?

c# - 关于检查空值的问题

.net - 如何在 .NET 中发布 Google Docs?

node.js - Node 和 npm 已安装,但 Git bash 无法识别 'node' 内的 'npm run dev'(其他 shell 工作正常)

ruby-on-rails - 警告 : circular argument reference - now when trying to open rails console

c# - 具有 5 个字符的 4x4 矩阵的所有组合

c# - C# 闭包对垃圾收集器的奇怪影响

windows - 在 Windows 上使用文件关闭进程