加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

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

发布时间:2020-12-13 21:04:49 所属栏目:Windows 来源:网络整理
导读:Related: 07000 07001 07002 我想构建一个控制台应用程序,这通常是从命令行运行的。 但是,当从资源管理器中双击(而不是从cmd.exe提示符运行)时,我希望该程序不显示控制台窗口。 我想避免这个: alt text http://i36.tinypic.com/1088p5s.jpg 可能吗? 编

Related:
07000
07001
07002

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

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

我想避免这个:

alt text http://i36.tinypic.com/1088p5s.jpg

可能吗?

编辑我猜另一种方式来问,是否可以让程序知道如何被调用 – 无论是通过双击还是通过命令行?

我在.NET上工作,在Windows上。

编辑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提示回来。如果有一个stdin / stdout,如果从cmd.exe运行,那么父cmd.exe等待进程退出。

“立即返回”很重要,因为如果您编写一个GUI应用程序来附加到其父级控制台,则可以执行console.writeline等。但是cmd.exe提示符是活动的。用户可以键入新的命令,开始一个新的进程,等等。换句话说,从winexe,只需使用AttachConsole(-1)附加到父控制台就不会将其“变成”一个控制台应用程序。

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

我还没有想到如何知道是从explorer还是cmd.exe启动,但是我越来越近了

解答

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

可以构建一个非常快速隐藏其窗口的控制台应用程序,但不会如此快,因为窗口不会出现。

现在,要确定是否从资源管理器启动了控制台应用程序,有些建议您查看正在运行的控制台
(mgb’s answer和KB article 99115):

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

这将告诉您进程是否在其自己的控制台中启动,而不是它是否是explorer。浏览器中的双击将会执行此操作,但是来自应用程序中的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应用程序。

这对我有用

见 Can a Win32 console application detect if it has been run from the explorer or not?

或者我认为官方的方法是检查父进程是cmd.exe还是explorer.exe

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读