96 votes

Peut-on exécutable être à la fois une console et de l'interface graphique de l'application?

Je veux faire un C# programme qui peut être exécuté comme un CLI ou de l'interface graphique de l'application en fonction de ce que les drapeaux sont passés dans celui-ci. Cela peut-il être fait?

J'ai trouvé ces questions, mais ils n'ont pas exactement le capot de ma situation:

114voto

Rob Kennedy Points 107381

Jdigital la réponse de points de Raymond Chen blog, ce qui explique pourquoi vous ne pouvez pas avoir une application qui est à la fois un programme de console et non de la console* programme: L'OS a besoin de savoir avant que le programme commence à courir sous-système à utiliser. Une fois que le programme a commencé en cours d'exécution, il est trop tard pour revenir en arrière et demander à l'autre mode.

Cade la réponse de points pour un article à propos de l'exécution d'un .Net WinForms application avec une console. Il utilise la technique de l'appel d' AttachConsole après le démarrage du programme en cours d'exécution. Cela a pour effet d'autoriser le programme à écrire de nouveau à la console de la fenêtre de l'invite de commande qui a démarré le programme. Mais les commentaires dans cet article le point de ce que je considère être une erreur fatale: Le processus de l'enfant ne contrôle pas vraiment la console. La console continue accepter l'entrée sur le nom du processus père et le processus parent ne sait pas qu'il faut attendre que l'enfant à la fin de course avant d'utiliser la console pour d'autres choses.

Chen article pointe vers un article de Junfeng Zhang qui explique un couple de d'autres techniques.

Le premier est ce que devenv utilise. Il fonctionne par le fait d'avoir deux programmes. L'un est devenv.exequi est l'interface graphique principale du programme, et l'autre est devenv.comqui gère en mode console tâches, mais si elle est utilisée dans un non-console-de la même manière, il transmet ses tâches à devenv.exe et les sorties. La technique repose sur le Win32 règle de com fichiers choisis à l'avance exe fichiers lorsque vous tapez une commande sans l'extension de fichier.

Il y a plus simple variation sur ce que Windows Script Host. Il fournit deux choses complètement distinctes binaires, wscript.exe et cscript.exe. De même, Java fournit java.exe pour les programmes de la console et javaw.exe pour les non-programmes de la console.

Junfeng la deuxième technique est ce que ildasm utilise. Il cite le processus qui ildasm'auteur est allé à travers quand le faire fonctionner dans les deux modes. En fin de compte, voici ce que l'on fait:

  1. Le programme est marqué comme une console en mode binaire, de sorte qu'il commence toujours avec une console. Cela permet l'entrée et la sortie de redirection à travailler comme d'habitude.
  2. Si le programme n'a pas de console en mode paramètres de ligne de commande, il se lance lui-même.

Il ne suffit pas de simplement appeler FreeConsole de faire la première instance de cesser d'être un programme en mode console. C'est parce que le processus qui a démarré le programme, cmd.exe, "sait" qu'il a commencé une console en mode programme et est en attente de l'arrêt du programme en cours d'exécution. Appelant FreeConsole ferait ildasm arrêter à l'aide de la console, mais ça ne ferait pas le parent processus de démarrage à l'aide de la console.

Donc, la première instance redémarre de lui-même (avec un supplément de paramètre de ligne de commande, je suppose). Lorsque vous appelez CreateProcess, il y a deux indicateurs différents pour essayer, DETACHED_PROCESS et CREATE_NEW_CONSOLE, soit de ce qui fera en sorte que la deuxième instance de ne pas être attaché à la mère de la console. Après cela, la première instance peut résilier et de permettre à l'invite de commande pour reprendre les commandes de traitement.

Les effets secondaires de cette technique est que lorsque vous démarrez le programme à partir d'une interface graphique, il y aura toujours une console. Il clignote momentanément sur l'écran, puis disparaissent.

La partie en Junfeng de l'article sur l'utilisation de editbin de modifier le programme en mode console de pavillon est un leurre, je pense. Votre compilateur ou de l'environnement de développement doit fournir un réglage ou une option pour contrôler le type de binaire, il crée. Il devrait y avoir aucun besoin de modifier quoi que ce soit par la suite.

La ligne de fond, alors, est que vous pouvez avoir deux fichiers binaires, ou vous pouvez avoir un scintillement momentané d'une fenêtre de console. Une fois que vous décidez ce qui est le moindre mal, vous avez votre choix de mises en œuvre.

* Je dis non de la console au lieu de GUI parce que sinon, c'est une fausse dichotomie. Juste parce qu'un programme n'a pas de console ne veut pas dire qu'il a une interface graphique. Une application de service est un premier exemple. Aussi, un programme peut avoir une console et windows.

11voto

jdigital Points 7425

Découvrez Raymond blog sur ce sujet:

http://blogs.msdn.com/oldnewthing/archive/2009/01/01/9259142.aspx

Sa première phrase: "Vous ne pouvez pas, mais vous pouvez essayer de faire semblant."

6voto

Cade Roux Points 53870

http://www.csharp411.com/console-output-from-winforms-application/

Il suffit de vérifier les arguments de ligne de commande avant de la WinForms Application. trucs.

Je dois ajouter que dans .NET, il est RIDICULEMENT facile de simplement faire une console et de l'interface graphique des projets dans la même solution qui partagent tous leurs assemblées, sauf principal. Et dans ce cas, vous pourriez faire la version en ligne de commande il suffit de lancer la version graphique si elle est lancée avec pas de paramètres. Vous souhaitez obtenir un clignotement de la console.

5voto

user1566352 Points 26

Il y a un moyen facile de faire ce que vous voulez. Je suis toujours à l'utiliser lors de l'écriture d'applications qui doivent avoir à la fois une interface CLI et GUI. Vous devez définir votre "Typesortie" à "ConsoleApplication" pour ce travail.

class Program {
  [DllImport("kernel32.dll", EntryPoint = "GetConsoleWindow")]
  private static extern IntPtr _GetConsoleWindow();

  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main(string[] args) {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    /*
     * This works as following:
     * First we look for command line parameters and if there are any of them present, we run the CLI version.
     * If there are no parameters, we try to find out if we are run inside a console and if so, we spawn a new copy of ourselves without a console.
     * If there is no console at all, we show the GUI.
     * We make an exception if we find out, that we're running inside visual studio to allow for easier debugging the GUI part.
     * This way we're both a CLI and a GUI.
     */
    if (args != null && args.Length > 0) {

      // execute CLI - at least this is what I call, passing the given args.
      // Change this call to match your program.
      CLI.ParseCommandLineArguments(args);

    } else {
      var consoleHandle = _GetConsoleWindow();

      // run GUI
      if (consoleHandle == IntPtr.Zero || AppDomain.CurrentDomain.FriendlyName.Contains(".vshost"))

        // we either have no console window or we're started from within visual studio
        // This is the form I usually run. Change it to match your code.
        Application.Run(new MainForm());
      else {

        // we found a console attached to us, so restart ourselves without one
        Process.Start(new ProcessStartInfo(Assembly.GetEntryAssembly().Location) {
          CreateNoWindow = true,
          UseShellExecute = false
        });
      }
    }
  }

3voto

gabeiscoding Points 384

Je pense que la technique privilégiée est ce que Rob appelé le devenv technique de l'utilisation de deux exécutables: un lanceur ".com" et l'original ".exe". Ce n'est pas difficile à utiliser si vous avez le code réutilisable (voir lien ci-dessous).

La technique utilise des astuces pour avoir ce ".com" être un proxy pour le stdin/stdout/stderr et lancer le même nom .exe fichier. Ce qui donne le comportement d'autoriser le programme à exécuter dans un mode de ligne de commande lorsqu'il est appelé à former une console (potentiellement seulement lorsque certains arguments de ligne de commande sont détectés) tout en étant capable de lancer une application graphique gratuite d'une console.

J'ai organisé un projet appelé dualsubsystem sur Google Code qui met à jour un vieux codeguru solution de cette technique et fournit le code source et de travail exemple des fichiers binaires.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X