2008-12-03 35 views
6

Estoy escribiendo una aplicación que se puede iniciar como una aplicación WinForms estándar o en modo desatendido desde la línea de comandos. La aplicación se creó utilizando la plantilla de WinForms estándar de VS 2k5.Salida a línea de comandos si se inició desde la línea de comandos

Cuando la aplicación se ejecuta desde la línea de comandos, quiero que muestre información que pueda ser capturada por el script que ejecuta la aplicación. Cuando hago esto directamente desde Console.WriteLine(), la salida no aparece, aunque se puede capturar mediante la canalización de un archivo.

Por otro lado, puedo forzar a la aplicación a que muestre una segunda consola haciendo una P/Invoke en AllocConsole() desde kernel32. Esto no es lo que quiero, sin embargo. Quiero que la salida aparezca en la misma ventana desde la que se llamó la aplicación.

Este es el código saliente que me permite que aparezca una consola desde la línea de comandos:

<STAThread()> Public Shared Sub Main() 

    If My.Application.CommandLineArgs.Count = 0 Then 
     Dim frm As New ISECMMParamUtilForm() 
     frm.ShowDialog() 
    Else 
     Try 
      ConsoleControl.AllocConsole() 
      Dim exMan As New UnattendedExecutionManager(ConvertArgs()) 
      IsInConsoleMode = True 
      OutputMessage("Application started.") 
      If Not exMan.SetSettings() Then 
       OutputMessage("Execution failed.") 
      End If 
     Catch ex As Exception 
      Console.WriteLine(ex.ToString()) 
     Finally 
      ConsoleControl.FreeConsole() 
     End Try 

    End If 

End Sub 

Public Shared Sub OutputMessage(ByVal msg As String, Optional ByVal isError As Boolean = False) 
    Trace.WriteLine(msg) 
    If IsInConsoleMode Then 
     Console.WriteLine(msg) 
    End If 

    If isError Then 
     EventLog.WriteEntry("ISE CMM Param Util", msg, EventLogEntryType.Error) 
    Else 
     EventLog.WriteEntry("ISE CMM Param Util", msg, EventLogEntryType.Information) 
    End If 

End Sub 

Respuesta

2

Actualización 1:

Como se ha dicho en respuesta a Michael Burr, Raymond Chen recientemente posted a short article about this. Estoy feliz de ver que mi conjetura no fue totalmente errónea.

Actualización de 0:

responsabilidad: Este "respuesta" es sobre todo la especulación. Lo publico solo porque ha pasado el tiempo suficiente para establecer que no muchas personas tienen la respuesta a lo que parece una pregunta fundamental.

Creo que la "decisión" si la aplicación es gui o consola se realiza en tiempo de compilación y no en tiempo de ejecución. Entonces, si compila su aplicación como aplicación gui, incluso si no muestra la GUI, sigue siendo una aplicación GUI y no tiene consola. Si elige compilarlo como aplicación de consola, como mínimo tendrá una ventana de consola parpadeando antes de pasar al modo "GUI". Y no sé si es posible en el código administrado.

El problema es fundamental, creo, porque una aplicación de consola tiene que tomar el "control" de la aplicación de la consola de llamadas. Y tiene que hacerlo antes de que se ejecute el código de la aplicación secundaria.

9

Raymond Chen publicado recientemente (un mes después de la pregunta fue publicada aquí en SO) un breve artículo acerca de esto:

How do I write a program that can be run either as a console or a GUI application?

No se puede, pero se puede tratar de fingir.

Cada aplicación PE contiene un campo en su cabecera que especifica el subsistema de que fue diseñado para funcionar bajo . Se puede decir IMAGE_SUBSYSTEM_WINDOWS_GUI para marcar a sí mismo como una aplicación GUI de Windows, o se puede decir IMAGE_SUBSYSTEM_WINDOWS_CUI decir que son una aplicación de consola. Si es una aplicación de GUI, entonces el programa se ejecutará sin una consola.

El subsistema determina cómo el kernel prepara el entorno de ejecución para el programa.Si el programa se marca como se ejecuta en el subsistema de consola, entonces el núcleo conectará la consola del programa para la consola de su padre, la creación de una nueva consola si el padre no tiene una consola. (Esta es una descripción incompleta , pero los detalles no son relevante a la discusión.) Por otra lado, si el programa está marcado como se ejecuta como una aplicación de interfaz gráfica de usuario, entonces el núcleo se ejecute el programa sin cualquier consola en absoluto.

En ese artículo se señala a otra por Junfeng Zhang que trata sobre cómo un par de programas (Visual Studio y ildasm) implementar este comportamiento:

How to make an application as both GUI and Console application?

En caso VisualStudio, hay en realidad dos binarios: devenv.com y devenv.exe. Devenv.com es una aplicación de consola. Devenv.exe es una aplicación GUI. Cuando escribe devenv, debido a la regla de prueba de Win32, se ejecuta devenv.com. Si no hay información, devenv.com inicia devenv.exe y se cierra. Si hay entradas, devenv.com las maneja como una aplicación de consola normal.

En caso de ildasm, solo hay un archivo binario: ildasm.exe. Primero se compila como una aplicación GUI. Más tarde, editbin.exe se usa para marcarlo como subsistema de consola. En su método principal, determina si debe ejecutarse como modo de consola o modo GUI. Si necesita ejecutarse como modo GUI, se relanza como una aplicación GUI.

En los comentarios al artículo de Raymond Chen, laonianren tiene esto para añadir a breve descripción de Zhang Junfeng de cómo funciona Visual Studio:

devenv.com es una aplicación en modo consola talón de propósito general. Cuando se ejecuta, crea tres tuberías para redirigir el stdin, stdout y stderr de la consola. Luego encuentra su propio nombre (generalmente devenv.com), reemplaza el ".com" por ".exe" y ejecuta la nueva aplicación (es decir, devenv.exe) utilizando el extremo de lectura de la tubería stdin y los extremos de escritura de la stdout y tubos stderr como los maneja estándar. Luego simplemente se sienta y espera a que devenv.exe salga y copie datos entre la consola y las tuberías.

Por lo tanto, aunque devenv.exe es una aplicación de interfaz gráfica de usuario, puede leer y escribir la consola "principal" con sus controladores estándar.

Y podría usar devenv.com para myapp.exe al cambiarle el nombre a myapp.com. Pero no se puede en la práctica porque pertenece a MS.

Cuestiones relacionadas