Laden...

Autoprompter für Konsole-Applikationen

Erstellt von svenson vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.458 Views
S
svenson Themenstarter:in
8.746 Beiträge seit 2005
vor 15 Jahren
Autoprompter für Konsole-Applikationen

Beschreibung:

Wer kennt das Problem nicht: Da hat man eine Konsolen-Applikation geschrieben und testet sie im Debugger aus, aber man kann die Ausgabe nicht lesen, weil das Fenster nach Beenden der Applikation sofort schliesst. Gleiches passiert mit Anwendungen die über den Explorer bzw. über Programme/Ausführen gestartet werden. Also baut man ein ReadLine() ein. Das nervt wiederum, wenn man die Anwendung direkt über cmd.exe ausführt.

Folgendes Snippet sorgt dafür, dass automatisch am Ende der Applikation eine Ausgabe und ein ReadLine() ausgeführt wird, sofern die Anwendung nicht direkt über eine Shell (cmd.exe) ausgeführt wird.

Hinweis: Mangels Prozess-Hierarchie in Windows wird hier mit Fenstern gearbeitet um herauszufinden, welches der Starter-Prozess ist. Das klappt im Normalfall, kann aber z.B. bei Batches oder Hintergrundjobs fehlschlagen.


   using System;
   using System.Collections.Generic;
   using System.Text;
   using System.Runtime.InteropServices;
   using System.Diagnostics;

   public class AutoPrompter : IDisposable
    {

        private const string DEFAULT_SHELL = "cmd";
        private const string DEFAULT_TEXT =   Environment.NewLine + @"Press <RETURN> to finish.";

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

        private List<string> commandShellsNames;

        private bool willPrompt;
        public bool WillPrompt
        {
            get { return willPrompt; }
        }

        private string closePromptText;
        public string ClosePromptText
        {
            get { return closePromptText; }
            set { closePromptText = value; }
        }

        private bool StartsFromCMD ( )
        {
            IntPtr ptr = GetForegroundWindow( );
            int u;
            GetWindowThreadProcessId( ptr, out u );
            Process process = Process.GetProcessById( u );
            return (commandShellsNames.IndexOf( process.ProcessName ) != -1);
        }

        public AutoPrompter ( string closePromptText ) 
        {
            Init( );
            this.closePromptText = closePromptText;
            SetStartMode( );
        }

        private void SetStartMode ( )
        {
            willPrompt = !StartsFromCMD( );
        }

        public AutoPrompter ( string closePromptText, string[] shells )
        {
            Init( );
            commandShellsNames.Clear( );
            commandShellsNames.AddRange( shells );
            this.closePromptText = closePromptText;
            SetStartMode( );
        }

        public AutoPrompter ( )
        {
            Init( );
            SetStartMode( );
        }

        protected virtual void DoPrompt ( )
        {
            Console.WriteLine( closePromptText );
            Console.ReadLine( );
        }

        private void Init ( )
        {
            commandShellsNames = new List<string>( );
            commandShellsNames.Add( DEFAULT_SHELL );
            this.closePromptText = DEFAULT_TEXT;
        }
      
        ~AutoPrompter ( )
        {
            Dispose( false );
        }

        public void Dispose ( )
        {
            Dispose( true );
            GC.SuppressFinalize( this );
        }

        private bool _disposed = false; // indicates if Dispose has been called

        private void Dispose ( bool disposing )
        {
            if ( !_disposed )
            {
                if ( disposing )
                {
                    if(willPrompt)
                        DoPrompt( );
                }

                _disposed = true;
            }
        }

    }

Benutzt wird das folgendermaßen:

public void Main()
{
    using( AutoPrompter prompt = new AutoPrompter("mein prompt Text"))
   {
        ... eigentlicher Code
   }
}

Statt mit using kann natürlich der Prompt explizit mit Dispose() ausgelöst werden.

Ein weiterer Konstruktor erlaubt die freie Definition der Shells (Standard ist cmd.exe). Shells bitte ohne die Endung ".exe" angeben.

console prompt cmd.exe auto

344 Beiträge seit 2007
vor 15 Jahren

Dake für das Snippet.

Ich füge immer eine "Pause" am Ende hinzu.
Damit bleibt die Konsole ebenfalls geöffnet.

👶-> :]-> 8o-> 🙂

R
234 Beiträge seit 2007
vor 15 Jahren

Dake für das Snippet.

Dem kann ich mich nur anschließen. Nettes Snippet 👍

Ich füge immer eine "Pause" am Ende hinzu.
Damit bleibt die Konsole ebenfalls geöffnet.

Wobei du dann ja wieder das Problem hast wie mit dem Console.ReadKey/ReadLine ... das wird ausgeführt unabhängig davon, ob man das Programm über die Konsole startet oder nicht. Für genau diese Fallunterscheidung sorgt ja das (super) Snippet. 🙂