gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 12:17:37 26 4
gpt4 key购买 nike

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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com