Skip to content
Advertisement

How to create a navigation menu in dotnet application?

I have created a console application which have a menu that allow me to navigate between the menu items. I handle the navigation logic in this method:

public virtual void updateMenu()
{
    switch (Console.ReadKey(true).Key)
    {
        case ConsoleKey.UpArrow:
            {
                if (cursor > 0)
                {
                    cursor--;
                    Console.Clear();
                    drawWithHeader();
                }
            }
            break;
        case ConsoleKey.DownArrow:
            {
                if (cursor < (menuItemList.Count - 1))
                {
                    cursor++;
                    Console.Clear();
                    drawWithHeader();
                }
            }
            break;
        case ConsoleKey.Escape:
            {
                if (ParentMenu != null)
                {

                    hideMenu();
                }
            }
            break;
        case ConsoleKey.Enter:
            {
                Console.Clear();
                drawHeader();
                Console.CursorVisible = true;
                menuItemList[cursor].Action();
                Console.CursorVisible = false;
                Console.Clear();
                drawWithHeader();
            }
            break;
        default:
            {
                // Unsuported key. Do nothing....
            }
            break;
    }
}

here the full class.

Now on windows all works well, but when I run this application on my linux with systemd I get:

Unhandled Exception: System.InvalidOperationException: Cannot read key when either application does not have a console or when console input has been redirected. Try Console.Read.

The stacktrace display:

at System.ConsolePal.ReadKey(Boolean intercept)
at System.Console.ReadKey();
at AppRazen.Menu.ConsoleMenu.UpdateMenu();  

After some searching I discovered that this problem is related to the ReadKey() method is not fully compatible with linux. And the solution proposed here simply doesn’t work in my case, because the user has used OminSharp.

I also tried to set ReadKey(false) but this didn’t fixed the problem, and I also tried to handle all the stuff inside UpdateMenu with Console.Read() but the console seems stuck.

Note that this issue will happen only when I run my script in linux supervisor not with the default command like dotnet AppRazen.dll

Essentially I’m running the script with a systemd service like this:

[Unit]
Description = Daemon description

[Service]
ExecStart = /usr/bin/dotnet /home/root/Desktop/publish/AppRazen.dll
WorkingDirectory= /home/root/Desktop/publish
Restart = always
RestartSec = 3

[Install]
WantedBy = multi-user.target

I honestly I don’t know how can I fix that. Someone have any ideas?

Thanks in advance.

Advertisement

Answer

The short answer to doing what you want to do is that you simply can’t.

Think about it: you are trying to have an interactive program (that users can interact with via the keyboard). But you are also making it a daemon (a deamon runs the background and doesn’t interact with users directly). These are two contradictory goals.

When systemd (or supervisord, or upstart or really any system services program) runs your application as a service, it doesn’t give it a way to interact with users, since these applications want to be daemons – which means users can’t interact with them.

So, ask yourself what you want to do: do you want to make an interactive program or not? If you want make an interactive program you can’t run it via supervisor. Run it directly, via dotnet /path/to/your.dll.

Other comments:

  • ReadKey may have issues, but certainly not in the common case that you are drying to do, which seems to be Linux on x86_64.

  • OmniSharp is a plugin for IDEs/text-editors to make development easier. It provides auto completion and real time syntax highlighting. It’s not involved when you are running your application.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement