是否可以创建一个控制台应用程序,当双击时不显示控制台窗口? [英] Is it possible to build a Console app that does not display a console Window when double-clicked?

查看:884
本文介绍了是否可以创建一个控制台应用程序,当双击时不显示控制台窗口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


相关:

我学到了一些好东西。这是我现在知道的...



在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)将不会转成一个控制台应用程序。






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



我仍然没有想过如何知道它是从explorer还是cmd.exe启动,但我越来越近了。






ANSWERS



应用程序,不显示控制台窗口。



可以 建立一个控制台应用程式,可以快速隐藏其窗口,但速度不会太快, 。



现在,为了确定是否从explorer启动了控制台应用程序,一些人建议查看它运行的控制台

(从< a href =http://stackoverflow.com/questions/1528152/is-it-possible-to-build-a-console-app-that-does-not-display-a-console-window-when/1528271# 1528271> mgb的回答和知识库文章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(进程名称:{0},name);
PerformanceCounter pc = new PerformanceCounter(Process,Creating Process Id,name);
Process p = Process.GetProcessById((int)pc.RawValue);
System.Console.WriteLine(父进程标识:{0},p.Id);
System.Console.WriteLine(父进程名称:{0},p.ProcessName);

// p.ProcessName ==cmd或Explorer等

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

  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应用程序。



这对我有用。

解决方案

查看一个Win32控制台应用程序可以检测它是否已从资源管理器运行?



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


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?

I want to build a console app, that is normally run from the command line.

But, when it is double clicked from within Explorer (as opposed to being run from a cmd.exe prompt) then I'd like the program to NOT display a console window.

I want to avoid this:

Is it possible?

EDIT I guess another way to ask it is, is it possible for a program to know how it was invoked - whether by double-click or by command line ?

I'm working in .NET, on Windows.

EDIT 2: From this Old New Thing blog post I learned some good stuff. Here's what I know now...

In Windows, EXE files are marked as either GUI or non-GUI. With csc.exe, this is selected with /target:winexe or /target:exe. Before the first instruction in the process executes, the Windows kernel sets up the execution environment. At that moment, if the EXE is marked GUI, the kernel sets the stdin/stdout for the process to NULL, and if non-GUI (command-line) the kernel creates a console and sets the stdin/stdout for the process to that console.

When launching the process, if there is no stdin/stdout (== /target:winexe), then the call immediately returns. So, launching a gui app from a cmd.exe, you will immediately get your cmd prompt back. If there is a stdin/stdout, and if run from cmd.exe, then the parent cmd.exe waits for process exit.

The "immediate return" is important because if you code a GUI app to attach to its parent's console, you will be able to do console.writeline, etc. But the cmd.exe prompt is active. The user can type new commands, start a new process, and so on. In other words, from a winexe, simply attaching to the parent console with AttachConsole(-1) will not "turn it into" a console app.


At this point I think the only way to allow an app to use the console if it is invoked from cmd.exe, and NOT use it if it is double-clicked, is to define the exe as a regular console exe (/target:exe), and hide the window on startup if appropriate. You still get a console window appearing briefly.

I still haven't figured how to know whether it was launched from explorer or cmd.exe, but I'm getting closer..


ANSWERS

It is not possible to build a console app that does not display a console window.

It is possible to build a console app that hides its window very quickly, but not so quickly that it is as if the window never appears.

Now, to determine whether a console app was launched from explorer, some have suggested to look at the console it is running in
(from mgb's answer, and KB article 99115) :

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

This tells you if the process was launched in its own console, but not whether it was explorer. A double click in explorer would do this, but also a Start.Process() from within an app would do the same thing.

If you want to treat those situations differently, use this to learn the name of the parent 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

To hide the window quickly after the process is launched, use this:

  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);
  }

If you produce a winexe (a WinForms app), and optionally attach to the parent console when appropriate with AttachConsole(-1), you do not get the equivalent of a regular console app. For a winexe, the parent process (like cmd.exe) will return to the command prompt immediately after starting a GUI application. In other words, the command prompt is active and ready for input while the just-launched process may be emitting output. This is confusing and is probably useful only for debugging winforms apps.

This worked for me.

解决方案

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

Or I think the official way is to check the parent process is cmd.exe or explorer.exe

这篇关于是否可以创建一个控制台应用程序,当双击时不显示控制台窗口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆