En utilisant AttachConsole, l'utilisateur doit appuyer sur Entrée pour obtenir la ligne de commande régulière

j'ai un progaram qui peut être exécuté à la fois comme winform, ou à partir de la ligne de commande. Si elle est invoquée à partir d'une ligne de commande, J'appelle AttachConsole(-1) à attacher à la console mère.

cependant, après la fin de mon programme, l'utilisateur doit appuyer sur Entrée pour récupérer l'invite de commande standard ("c:>"). est-il un moyen pour éviter ce besoin?

Merci. J'ai pu l'envelopper dans un fichier cmd pour éviter ce problème, mais je voudrais le faire à partir de mon exe.

19
demandé sur Leon Bambrick 2009-08-20 14:31:58

5 réponses

Essayez d'ajouter cette ligne juste avant votre exe sorties...

Système.Windows.Forme.SendKeys.SendWait ("{ENTER}");

un peu un piratage, mais le mieux que j'ai pu trouver quand j'ai rencontré ce problème.

Rob

17
répondu Rob L 2010-03-17 14:29:38

L'approche de Rob L est quelque peu dangereuse car elle envoie une entrée à la fenêtre active. Une meilleure approche consiste à envoyer réellement la saisie au processus correct (console).

ici est de savoir comment

    internal static class NativeMethods
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern bool AllocConsole();

        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern bool FreeConsole();

        [DllImport("kernel32", SetLastError = true)]
        internal static extern bool AttachConsole(int dwProcessId);

        [DllImport("user32.dll")]
        internal static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll", SetLastError = true)]
        internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

        [DllImport("User32.Dll", EntryPoint = "PostMessageA")]
        internal static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);

        internal const int VK_RETURN = 0x0D;
        internal const int WM_KEYDOWN = 0x100;
    }

-- snip--

            bool attached = false;

            // Get uppermost window process
            IntPtr ptr = NativeMethods.GetForegroundWindow();
            int u;
            NativeMethods.GetWindowThreadProcessId(ptr, out u);
            Process process = Process.GetProcessById(u);

            if (string.Compare(process.ProcessName, "cmd", StringComparison.InvariantCultureIgnoreCase) == 0)
            {
                // attach to the current active console
                NativeMethods.AttachConsole(process.Id);
                attached = true;
            }
            else
            {
                // create new console
                NativeMethods.AllocConsole();
            }

            Console.Write("your output");

            NativeMethods.FreeConsole();

            if (attached)
            {
                var hWnd = process.MainWindowHandle;
                NativeMethods.PostMessage(hWnd, NativeMethods.WM_KEYDOWN, NativeMethods.VK_RETURN, 0);
            }

cette solution est basée sur le code qui se trouve ici:

http://www.jankowskimichal.pl/en/2011/12/wpf-hybrid-application-with-parameters/

3
répondu invalidusername 2015-11-03 16:37:44

Ok, je n'ai pas la solution, mais il semble que ce soit parce que le cmd.exe n'attend pas le début du processus, alors qu'avec une application normale sur console cmd.exe attend la sortie de l'application. Je ne sais pas ce qui fait le cmd.exe décider d'attendre ou pas sur une application, les applications normales de formulaires Windows sont juste commencé et cmd.exe n'a pas l'attendre à la sortie. Peut-être que cet indice déclenche quelqu'un! Je vais creuser un peu plus profondément dans le temps.

Wout

2
répondu Wout 2010-08-25 13:11:14

Essayez d'appeler le FreeConsole fonction avant de quitter votre exécutable.

1
répondu Nick 2010-03-17 15:14:38

voici le hack le plus sûr qui résout le problème de la touche Entrée, que la fenêtre de la console soit au premier plan, en arrière-plan ou minimisée. Vous pouvez même l'exécuter dans plusieurs fenêtres de console.

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace WindowsAndConsoleApp
{
  static class Program
  {
    const uint WM_CHAR = 0x0102;
    const int VK_ENTER = 0x0D;

    [DllImport("kernel32.dll")]
    static extern bool AttachConsole(int dwProcessId);
    private const int ATTACH_PARENT_PROCESS = -1;

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool FreeConsole();

    [DllImport("kernel32.dll")]
    static extern IntPtr GetConsoleWindow();

    [DllImport("user32.dll")]
    static extern int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

    [STAThread]
    static void Main(string[] args)
    {
        if (args.Length > 0)
        {
            // Do this first.
            AttachConsole(ATTACH_PARENT_PROCESS);

            Console.Title = "Console Window - Enter Key Test";
            Console.WriteLine("Getting the handle of the currently executing console window...");
            IntPtr cw = GetConsoleWindow();
            Console.WriteLine($"Console handle: {cw.ToInt32()}");
            Console.WriteLine("\nPut some windows in from of this one...");
            Thread.Sleep(5000);
            Console.WriteLine("Take your time...");
            Thread.Sleep(5000);
            Console.WriteLine("Sending the Enter key now...");

            // Send the Enter key to the console window no matter where it is.
            SendMessage(cw, WM_CHAR, (IntPtr)VK_ENTER, IntPtr.Zero);

            // Do this last.
            FreeConsole();
        }
        else
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
  }
}
1
répondu CaymanRich 2017-08-10 17:33:47