开发者

'Advanced' Console Application

开发者 https://www.devze.com 2023-02-02 08:14 出处:网络
I\'m not sure if this question开发者_如何学运维 has been answered elsewhere and I can\'t seem to find anything through google that isn\'t a \"Hello World\" example...I\'m coding in C# .NET 4.0.

I'm not sure if this question开发者_如何学运维 has been answered elsewhere and I can't seem to find anything through google that isn't a "Hello World" example... I'm coding in C# .NET 4.0.

I'm trying to develop a console application that will open, display text, and then wait for the user to input commands, where the commands will run particular business logic.

For example: If the user opens the application and types "help", I want to display a number of statements etc etc. I'm not sure how to code the 'event handler' for user input though.

Hopefully this makes sense. Any help would be much appreciated! Cheers.


You need several steps to achieve this but it shouldn't be that hard. First you need some kind of parser that parses what you write. To read each command just use var command = Console.ReadLine(), and then parse that line. And execute the command... Main logic should have a base looking this (sort of):

public static void Main(string[] args)
{
    var exit = false;
    while(exit == false)
    {
         Console.WriteLine();
         Console.WriteLine("Enter command (help to display help): "); 
         var command = Parser.Parse(Console.ReadLine());
         exit = command.Execute();
    }
}

Sort of, you could probably change that to be more complicated.

The code for the Parser and command is sort of straight forward:

public interface ICommand
{
    bool Execute();
}

public class ExitCommand : ICommand
{
    public bool Execute()
    {
         return true;
    }
}

public static Class Parser
{
    public static ICommand Parse(string commandString) { 
         // Parse your string and create Command object
         var commandParts = commandString.Split(' ').ToList();
         var commandName = commandParts[0];
         var args = commandParts.Skip(1).ToList(); // the arguments is after the command
         switch(commandName)
         {
             // Create command based on CommandName (and maybe arguments)
             case "exit": return new ExitCommand();
               .
               .
               .
               .
         }
    }
}


I know this is an old question, but I was searching for an answer too. I was unable to find a simple one though, so I built InteractivePrompt. It's available as a NuGet Package and you can easily extend the code which is on GitHub. It features a history for the current session also.

The functionality in the question could be implemented this way with InteractivePrompt:

static string Help(string strCmd)
{
    // ... logic
    return "Help text";
}
static string OtherMethod(string strCmd)
{
    // ... more logic
    return "Other method";
}
static void Main(string[] args)
{
    var prompt = "> ";
    var startupMsg = "BizLogic Interpreter";
    InteractivePrompt.Run(
        ((strCmd, listCmd) =>
        {
            string result;
            switch (strCmd.ToLower())
            {
                case "help":
                    result = Help(strCmd);
                    break;
                case "othermethod":
                    result = OtherMethod(strCmd);
                    break;
                default:
                    result = "I'm sorry, I don't recognize that command.";
                    break;
            }

            return result + Environment.NewLine;
        }), prompt, startupMsg);
}


This is easy enough, just use the Console.WriteLine and Console.ReadLine() methods. From the ReadLine you get a string. You could have a horrible if statement that validate this against known/expected inputs. Better would be to have a lookup table. Most sophisticated would be to write a parser. It really depends on how complex the inputs can be.


Console.WriteLine Console.ReadLine and Console.ReadKey are your friends. ReadLine and ReadKey waits for user input. The string[] args will have all of your parameters such as 'help' in them. The array is created by separating the command line arguments by spaces.


switch (Console.ReadLine())
{
    case "Help":
        // print help
        break;

    case "Other Command":
        // do other command
        break;

    // etc.

    default:
        Console.WriteLine("Bad Command");
        break;
}

If you're looking to parse commands that have other things in them like parameters, for example "manipulate file.txt" then this alone won't work. But you could for example use String.Split to separate the input into a command and arguments.


A sample:

    static void Main(string[] args)
    {
        Console.WriteLine("Welcome to test console app, type help to get some help!");

        while (true)
        {
            string input = Console.ReadLine();

            int commandEndIndex = input.IndexOf(' ');

            string command = string.Empty;
            string commandParameters = string.Empty;

            if (commandEndIndex > -1)
            {
                command = input.Substring(0, commandEndIndex);
                commandParameters = input.Substring(commandEndIndex + 1, input.Length - commandEndIndex - 1);
            }
            else
            {
                command = input;
            }

            command = command.ToUpper();

            switch (command)
            {
                case "EXIT":
                    {
                        return;
                    }
                case "HELP":
                    {
                        Console.WriteLine("- enter EXIT to exit this application");
                        Console.WriteLine("- enter CLS to clear the screen");
                        Console.WriteLine("- enter FORECOLOR value to change text fore color (sample: FORECOLOR Red) ");
                        Console.WriteLine("- enter BACKCOLOR value to change text back color (sample: FORECOLOR Green) ");
                        break;
                    }
                case "CLS":
                    {
                        Console.Clear();
                        break;
                    }

                case "FORECOLOR":
                    {
                        try
                        {
                            Console.ForegroundColor = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), commandParameters);
                        }
                        catch
                        {
                            Console.WriteLine("!!! Parameter not valid");
                        }

                        break;
                    }
                case "BACKCOLOR":
                    {
                        try
                        {
                            Console.BackgroundColor = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), commandParameters);
                        }
                        catch
                        {
                            Console.WriteLine("!!! Parameter not valid"); 
                        }

                        break;
                    }
                default:
                    {
                        Console.WriteLine("!!! Bad command");
                        break;
                    }
            }
        }
    }


This is very simplistic, but might meet your needs.

// somewhere to store the input
string userInput="";

// loop until the exit command comes in.
while (userInput != "exit")
{
    // display a prompt
    Console.Write("> ");
    // get the input
    userInput = Console.ReadLine().ToLower();

    // Branch based on the input
    switch (userInput)
    {
        case "exit": 
          break;

        case "help": 
        {
          DisplayHelp(); 
          break;
        }

        case "option1": 
        {
          DoOption1(); 
          break;
        }

        // Give the user every opportunity to invoke your help system :)
        default: 
        {
          Console.WriteLine ("\"{0}\" is not a recognized command.  Type \"help\" for options.", userInput);
          break;
        }
    }
}


There is a C# nuget package called 'ReadLine' by 'tornerdo'. The statement ReadLine.Read(" prompt > "); prompts the user within options provided in CustomAutoCompletionHandler.PossibleAutoCompleteValues.

Additionally, you can change the CustomAutoCompletionHandler.PossibleAutoCompleteValues for each prompt. This ensures that the user get to choose an option from available\ supported list of options. Less error prone.

static void Main(string[] args)
{
    Console.ForegroundColor = ConsoleColor.Cyan;
    Console.WriteLine(" Note! When it prompts, press <tab> to get the choices. Additionally, you can use type ahead search.");
    Console.ForegroundColor = ConsoleColor.White;

    // Register auto completion handler..
    ReadLine.AutoCompletionHandler = new CustomAutoCompletionHandler();

    CustomAutoCompletionHandler.PossibleAutoCompleteValues = new List<string> { "dev", "qa", "stg", "prd" };
    var env = CoverReadLine(ReadLine.Read("  Environment > "));
    Console.WriteLine($"Environment: {env}");
}

private static string CoverReadLine(string lineRead) => CustomAutoCompletionHandler.PossibleAutoCompleteValues.Any(x => x == lineRead) ? lineRead : throw new Exception($"InvalidChoice. Reason: No such option, '{lineRead}'");
        
public class CustomAutoCompletionHandler : IAutoCompleteHandler
{
    public static List<string> PossibleAutoCompleteValues = new List<string> { };

    // characters to start completion from
    public char[] Separators { get; set; } = new char[] { ' ', '.', '/' };

    // text - The current text entered in the console
    // index - The index of the terminal cursor within {text}
    public string[] GetSuggestions(string userText, int index)
    {
        var possibleValues = PossibleAutoCompleteValues.Where(x => x.StartsWith(userText, StringComparison.InvariantCultureIgnoreCase)).ToList();
        if (!possibleValues.Any()) possibleValues.Add("InvalidChoice");
        return possibleValues.ToArray();
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消