relacionadas:
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?¿Es posible crear una aplicación de consola que no muestre una ventana de consola cuando se hace doble clic en ella?
Quiero construir una aplicación de consola, que normalmente se ejecuta desde la línea de comandos.
Pero, cuando se hace doble clic desde Explorer (en lugar de ejecutarlo desde el símbolo del sistema cmd.exe), me gustaría que el programa NO muestre una ventana de consola.
quiero evitar esto:
alt text http://i36.tinypic.com/1088p5s.jpg
¿Es posible?
EDITAR supongo otra forma de preguntar es, es posible que un programa para conocer la forma en que se invocó - ya sea haciendo doble clic o mediante línea de comandos?
Estoy trabajando en .NET, en Windows.
EDIT 2: De this Old New Thing blog post aprendí algunas cosas buenas. Esto es lo que sé ahora ...
En Windows, los archivos EXE están marcados como GUI o como GUI. Con csc.exe, esto se selecciona con /target:winexe
o /target:exe
. Antes de que se ejecute la primera instrucción en el proceso, el núcleo de Windows configura el entorno de ejecución. En ese momento, si el EXE está marcado GUI, el kernel establece stdin/stdout para el proceso en NULL, y si no es GUI (línea de comandos), el kernel crea una consola y establece el stdin/stdout para el proceso a ese consola.
Al iniciar el proceso, si no hay stdin/stdout (== /target:winexe
), la llamada vuelve inmediatamente. Por lo tanto, al iniciar una aplicación gui desde un cmd.exe, recuperará de inmediato su solicitud de cmd. Si hay un stdin/stdout, y si se ejecuta desde cmd.exe, el cmd.exe padre espera la salida del proceso.
La "devolución inmediata" es importante porque si codifica una aplicación GUI para adjuntarla a la consola de su padre, podrá hacer console.writeline, etc. Pero el aviso de cmd.exe está activo. El usuario puede escribir nuevos comandos, iniciar un nuevo proceso, etc. En otras palabras, desde un winexe, simplemente adjuntar a la consola principal con AttachConsole(-1)
no "convertirá" en una aplicación de consola.
En este punto, creo que la única manera de permitir que una aplicación utilice la consola si se invoca desde cmd.exe, y no utilizarla si se hace doble clic, es definir el exe como la consola regular exe (/target:exe
) y ocultan la ventana en el inicio si corresponde. Todavía obtienes una ventana de consola que aparece brevemente.
Todavía no sé cómo se inició desde explorer o cmd.exe, pero me estoy acercando ...
RESPUESTAS
No es posible construir una aplicación de consola que no muestra una ventana de consola.
es posible construir una aplicación de consola que oculta su ventana muy rápidamente, pero no tan rápido que es como si la ventana nunca aparece.
Ahora, para determinar si una aplicación de consola fue lanzada desde el explorador, algunos han sugerido que mirar la consola se está ejecutando en
(de mgb's answer y KB article 99115):
int left = Console.CursorLeft;
int top = Console.CursorTop;
bool ProcessWasRunFromExplorer = (left==0 && top==0);
Esto le indica si el proceso se inició en su propia consola, pero no si fue explorador. Un doble clic en el explorador haría esto, pero también un Start.Process() desde dentro de una aplicación haría lo mismo.
Si usted quiere tratar esas situaciones de manera diferente, usar esto para conocer el nombre del proceso padre:
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
Para ocultar la ventana rápidamente después de que se puso en marcha el proceso, utilice esto:
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);
}
Si genera winexe
(una aplicación de WinForms) y, opcionalmente, se conecta a la consola principal cuando corresponda con AttachConsole(-1)
, no obtendrá el equivalente de una aplicación de consola normal. Para un winexe, el proceso primario (como cmd.exe) volverá al símbolo del sistema inmediatamente después de iniciar una aplicación GUI. En otras palabras, el símbolo del sistema está activo y listo para la entrada mientras que el proceso recién lanzado puede estar emitiendo salida. Esto es confuso y probablemente solo sea útil para depurar aplicaciones de winforms.
Esto funcionó para mí.
¿Qué te gustaría que hiciera? –
Quiero que sea invisible. – Cheeso
La prueba para determinar si el programa se inició en su propia consola es incorrecta. Ingresar 'cls & program.exe' en la línea de comando indicará erróneamente que el programa se inició en su propia consola. Podría hacer lo mismo desde un archivo por lotes. Probablemente haya otras maneras de vencer la prueba. –