2009-08-20 18 views
19

Tengo un programa que se puede ejecutar tanto como un formulario de win, o desde la línea de comandos. Si se invoca desde una línea de comando, llamo a AttachConsole (-1) para adjuntarlo a la consola principal.Usando AttachConsole, el usuario debe presionar enter para obtener la línea de comando regular

Sin embargo, una vez que finaliza mi programa, el usuario debe presionar enter para recuperar el símbolo del sistema estándar ("c: \>"). ¿Hay alguna forma de evitar esa necesidad?

Gracias. Podría envolverlo en un archivo cmd para evitar ese problema, pero me gustaría hacerlo desde mi archivo .exe.

+1

¿Alguna vez descubrió esto? Tengo lo mismo y me gustaría saber si hay un problema. – cgyDeveloper

+1

No, no lo he hecho. Lo siento. – Clangon

+0

Mismo problema aquí. El usuario está en una línea de comando estándar, pero el mensaje no se muestra (hasta que presionen enter, para volver a mostrarlo) –

Respuesta

17

Trate de añadir esta línea justo antes de sus salidas exe ...

System.Windows.Forms.SendKeys.SendWait ("{ENTER}");

Un truco, pero lo mejor que pude encontrar fue cuando encontré ese problema.

Rob

+0

Funcionó, gracias. – Clangon

+0

LOL, esto es realmente lo obvio, pero no pude entenderlo antes de buscar en Google: P – kizzx2

+2

Esto parece realmente malo, pero parece ser la única forma aparente de hacerlo. Gracias. – mbrownnyc

1

Intente llamar a la función FreeConsole antes de salir de su ejecutable.

+6

Ya lo he intentado, parece que no funciona. gracias de cualquier manera. – Clangon

1

Ok, no tengo la solución, pero parece ser debido a que el cmd.exe no está esperando en el proceso iniciado, mientras que con una aplicación de consola normales espera hasta que el cmd.exe la la aplicación sale No sé qué hace que cmd.exe decida esperar o no en una aplicación, las aplicaciones normales de Windows Forms se acaban de iniciar y cmd.exe no espera a que salga. Tal vez esta sugerencia desencadena a alguien! Voy a cavar un poco más profundo en el tiempo.

Wout

3

enfoque Rob L's es algo peligroso, ya que enviará un Ingrese a la ventana activa. Un mejor enfoque es enviar el Enter al proceso correcto (consola).

aquí es cómo

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); 
      } 

Esta solución se construye sobre el código que se encuentra aquí:

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

+0

En realidad, no crees un programa que sea una GUI y una aplicación de consola al mismo tiempo ... lee esto: http://stackoverflow.com/questions/493536/can-one-executable-be-both-a- console-and-gui-application/494000 # 494000 – invalidusername

+1

Acepto que la solución de Rob no es segura, pero parece que su respuesta sufre el mismo problema mediante el uso de GetForegroundWindow. Tal vez use una API para ver qué proceso inició su aplicación, o use GetConsoleProcessList. – Herman

1

Aquí es el el truco más seguro que resuelve el problema de la tecla Intro sin importar si la ventana de la consola está en t el primer plano, el fondo o minimizado. Incluso puede ejecutarlo en varias ventanas de la consola.

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()); 
     } 
    } 
    } 
} 
+0

Esta es la respuesta que ayudó a resolver mi problema. Sé que esto es casi medio año después, ¡pero gracias! – Chris

Cuestiones relacionadas