2011-10-26 6 views
8

Quiero crear una aplicación que se comporta de la siguiente manera:¿Cómo manejo los argumentos de línea de comando en Winforms si no quiero cargar el formulario principal?

  1. En ningún argumento que muestra el formulario principal
  2. El argumento "a" hace no se ha cargado un trabajo, pero la forma principal.
  3. En argumento "b" se carga el formulario utilizando el argumento pasado (cargar ese documento)

Para el 1 y 3 que puede manejar los argumentos en el constructor del formulario como sigue:

public ConfigurationActionManagerForm() 
{ 
    InitializeComponent(); 
    Environment.GetCommandLineArgs(); 
    // do stuff with that argument 
} 

Pero este enfoque no me permite aplicar el comportamiento de 2. en la lista.

En program.cs puedo editarlo para manejar los argumentos incluso antes de que se cree el formulario, pero ¿cuál es el enfoque correcto al usar Application.Run() si no quiero pasar un formulario? ¿Cómo voy a informar a la instancia de clase Program que necesito terminar o mostrar un mensaje de que algo salió mal o incluso mostrar un pequeño ícono de la barra de tareas que el proceso está haciendo cosas (piénsalo como el proceso de descompresión).

[STAThread] 
static void Main() 
{ 
    Application.EnableVisualStyles(); 
    Application.SetCompatibleTextRenderingDefault(false); 
    Application.Run(new ConfigurationActionManagerForm()); 
} 

Would this enfoque de MSDN es correcta a mi solicitud?

Respuesta

2

he encontrado una solución limpia y fácil de implementar utilizando el ejemplo de la mi pregunta proporcionada por microsoft.

Creé esta clase de contexto de aplicación que es responsable de todo en la aplicación y la utilizo en lugar de un formulario en el Application.Run() como se muestra a continuación. Para lograr el comportamiento en la pregunta, estoy usando un segundo formulario que está oculto y solo se muestra el ícono de la barra de tareas. Si el usuario desea ver cómo está el proceso, puede hacer clic en el icono de la barra de tareas y ver la ventana de registro, que en realidad es ConfigurationApplierForm en el siguiente ejemplo.

class AnApplicationContext: ApplicationContext 
{ 
private Form _currentForm; 

Nota del constructor es privado, el principal es el interior de esta clase y declararon estática.

private AnApplicationContext() 
{ 
    Application.ApplicationExit += new EventHandler(this.OnApplicationExit); 

    // choose which form to show based on arguments 
    if(Environment.GetCommandLineArgs().Contains("-apply")) 
    { 
     _currentForm = new ConfigurationApplierForm(); 
    } 
    else 
    { 
     _currentForm = new ConfigurationActionManagerForm(); 
    } 

    // initialize the form and attach event handlers 
    _currentForm.FormClosed += new FormClosedEventHandler(this.OnCurrentFormClosed); 
    _currentForm.ShowDialog(); 
} 

Principal está aquí, un poco diferente del original. Note el argumento en el método Run

[STAThread] 
static void Main() 
{ 
    Application.EnableVisualStyles(); 
    Application.SetCompatibleTextRenderingDefault(false); 
    // context is passed instead of a form 
    Application.Run(new AnApplicationContext()); 
} 

private void OnCurrentFormClosed(object sender, EventArgs e) 
{ 
    ExitThread(); 
} 

private void OnApplicationExit(object sender, EventArgs e) 
{ 
    /* is there anything to do when all forms are closed 
    and the application is going to die?*/ 
} 
} 

Además, tenemos que decirle al proyecto que este es el proyecto de inicio.

Project Properties -> Application -> Startup Project 
3

Puede llamar a Application.Run() sin una instancia de formulario.

De esta manera, iniciará el ciclo de mensajes sin abrir un formulario.

Puede llamar a MessageBox.Show() antes de llamar .Run(), también.

Incluso puede crear y abrir un formulario, y luego llamar a Run() sin especificar un argumento, simplemente significa que el cierre del formulario no sale automáticamente de la aplicación.

E.g.

 MessageBox.Show("Messaage!"); 

     Form1 f = new Form1(); 
     f.Show(); 

     Application.Run(); 

Como se ha dicho anteriormente, esta forma de hacer Run() significa que el cierre de las formas no se cierra automáticamente la aplicación. Debe manejar esto en el controlador de eventos Close del formulario. (Application.Exit())

MSDN en línea puede ayudarlo con esto - consulte la entrada de ayuda para Application.Run().

7

¿Te refieres a la misma manera que funciona Visual Studio?

Si es así, entonces no puede hacer esto en una aplicación normal de Windows: trucos de Visual Studio.

El problema es que una aplicación de Windows puede ser una aplicación de Windows Forms o una aplicación de consola, pero no puede ser ambas: se decide en tiempo de compilación (para aplicaciones .Net esta se encuentra en la ventana de propiedades del proyecto). Las opciones son:

que su aplicación sea una aplicación Windows Forms

En este caso # 1 y # 3 funcionará perfecty, pero para # 2 se encuentra que no se puede leer desde/escribir en la consola (porque no hay una!).Si su appliction no necesita indicar que la pregunta entonces esto podría ser bien - hacer su trabajo como lo haría normalmente, y simplemente no mostrar un formulario:

[STAThread] 
static void Main(string[] args) 
{ 
    if (args.Length > 0) 
    { 
     // Handle #2 here 
    } 
    else 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new ConfigurationActionManagerForm()); 
    } 
} 

que su aplicación sea una aplicación de consola

En este caso, el # 2 funcionará perfectamente; sin embargo, aunque los números 1 y 3 funcionarán correctamente, siempre tendrá la ventana de la consola abierta en segundo plano; si cierra la ventana de la consola, la aplicación finalizará.

De nuevo, esto podría estar bien, pero personalmente encuentro que esto es un truco.

tramposo (hacer lo que Visual Studio no)

tramposos Visual Studio por tener 2 aplicaciones separadas - uno es una aplicación de consola y la otra es una aplicación Windows Forms. La solución fácil es dejarlo así y exigir que los usuarios comiencen un ejecutable diferente cuando ejecuten la versión de línea de comando (por ejemplo, myprogram_g.exe y myprogram_w.exe).

Visual Studio va un paso más allá y tiene un solo punto de entrada, devenv. Lo hace utilizando el hecho de que, por razones de compatibilidad, el shell de Windows siempre ejecutará un archivo .com en lugar de .exe si existe alguna ambigüedad. Si todos los accesos directos apuntan al ejecutable, si ejecuta devenv en la línea de comandos, se ejecutará la aplicación devenv.com que utiliza magia para determinar si se ejecuta o no como consola o aplicación de Windows.

Mi consejo sería crear dos aplicaciones diferentes y dejarlo así.

Consulte How do I write a program that can be run either as a console or a GUI application? para obtener más información (asegúrese de leer los comentarios que tienen sugerencias útiles adicionales).

También vea How to make an application as both GUI and Console application? para ver cómo ildasm hace esto.

1

Básicamente, desea una aplicación de consola con algunos cambios.

Aquí hay un ejemplo de cómo empezar, el uso de una clase AboutBox defecto:

using System; 
using System.Windows.Forms; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      if (args.Length == 0) 
      { 
       Console.WriteLine("No Arguments"); 
      } 
      else 
      { 
       if (args[0] == "a") 
       { 
        Application.EnableVisualStyles(); 
        Application.SetCompatibleTextRenderingDefault(false); 
        Application.Run(new AboutBox1()); 

       } 
      } 

     } 
    } 
} 

Y AboutBox1 clase:

using System.Reflection; 
using System.Windows.Forms; 

namespace ConsoleApplication1 
{ 
    partial class AboutBox1 : Form 
    { 
     public AboutBox1() 
     { 
      InitializeComponent(); 
      this.Text = String.Format("About {0} {0}", AssemblyTitle); 
      this.labelProductName.Text = AssemblyProduct; 
      this.labelVersion.Text = String.Format("Version {0} {0}", AssemblyVersion); 
      this.labelCopyright.Text = AssemblyCopyright; 
      this.labelCompanyName.Text = AssemblyCompany; 
      this.textBoxDescription.Text = AssemblyDescription; 
     } 

     #region Assembly Attribute Accessors 

     public string AssemblyTitle 
     { 
      get 
      { 
       object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false); 
       if (attributes.Length > 0) 
       { 
        AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0]; 
        if (titleAttribute.Title != "") 
        { 
         return titleAttribute.Title; 
        } 
       } 
       return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase); 
      } 
     } 

     public string AssemblyVersion 
     { 
      get 
      { 
       return Assembly.GetExecutingAssembly().GetName().Version.ToString(); 
      } 
     } 

     public string AssemblyDescription 
     { 
      get 
      { 
       object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); 
       if (attributes.Length == 0) 
       { 
        return ""; 
       } 
       return ((AssemblyDescriptionAttribute)attributes[0]).Description; 
      } 
     } 

     public string AssemblyProduct 
     { 
      get 
      { 
       object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); 
       if (attributes.Length == 0) 
       { 
        return ""; 
       } 
       return ((AssemblyProductAttribute)attributes[0]).Product; 
      } 
     } 

     public string AssemblyCopyright 
     { 
      get 
      { 
       object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); 
       if (attributes.Length == 0) 
       { 
        return ""; 
       } 
       return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; 
      } 
     } 

     public string AssemblyCompany 
     { 
      get 
      { 
       object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); 
       if (attributes.Length == 0) 
       { 
        return ""; 
       } 
       return ((AssemblyCompanyAttribute)attributes[0]).Company; 
      } 
     } 
     #endregion 

     private void okButton_Click(object sender, EventArgs e) 
     { 
      Close(); 
     } 
    } 
} 
Cuestiones relacionadas