如何在 dotnet 应用程序中创建导航菜单?
How to create a navigation menu in dotnet application?
我创建了一个控制台应用程序,它有一个菜单,允许我在菜单项之间导航。我用这个方法处理导航逻辑:
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;
}
}
现在在 windows 上一切正常,但是当我 运行 在我的 linux 上使用 systemd
这个应用程序时,我得到:
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.
堆栈跟踪显示:
at System.ConsolePal.ReadKey(Boolean intercept)
at System.Console.ReadKey();
at AppRazen.Menu.ConsoleMenu.UpdateMenu();
经过一番搜索,我发现这个问题与 ReadKey()
方法不完全有关 . And the solution proposed 在我的情况下根本不起作用,因为用户已经使用 OminSharp
.
我也尝试设置 ReadKey(false)
但这并没有解决问题,我也尝试用 Console.Read()
处理 UpdateMenu
里面的所有东西但是控制台似乎卡住了.
请注意,只有当我 运行 我在 linux supervisor 中的脚本不使用 dotnet AppRazen.dll
这样的默认命令时才会发生此问题
本质上,我 运行 使用这样的 systemd
服务来编写脚本:
[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
老实说,我不知道该如何解决。有人有什么想法吗?
提前致谢。
做你想做的事情的简短回答是你根本做不到。
想一想:您正在尝试创建一个交互式程序(用户可以通过键盘与之交互)。但是您还使它成为守护进程(守护进程 运行 处于后台并且不直接与用户交互)。这是两个相互矛盾的目标。
当 systemd
(或 supervisord
,或 upstart
或任何系统服务程序)运行将您的应用程序作为服务时,它不会提供一种与用户交互的方式,因为这些应用程序希望成为守护进程 - 这意味着用户无法与它们交互。
所以,问问自己你想做什么:你想不想做一个互动程序?如果你想制作一个交互式程序,你不能 运行 通过主管。 运行 直接通过 dotnet /path/to/your.dll
.
其他评论:
ReadKey
可能有问题,但肯定不是你正在干的常见情况,这似乎是 Linux 对 x86_64。
OmniSharp 是 IDEs/text-editors 的一个插件,可以简化开发。它提供自动完成和实时语法突出显示。当您 运行 应用程序时,它不涉及。
我创建了一个控制台应用程序,它有一个菜单,允许我在菜单项之间导航。我用这个方法处理导航逻辑:
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;
}
}
现在在 windows 上一切正常,但是当我 运行 在我的 linux 上使用 systemd
这个应用程序时,我得到:
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.
堆栈跟踪显示:
at System.ConsolePal.ReadKey(Boolean intercept)
at System.Console.ReadKey();
at AppRazen.Menu.ConsoleMenu.UpdateMenu();
经过一番搜索,我发现这个问题与 ReadKey()
方法不完全有关 OminSharp
.
我也尝试设置 ReadKey(false)
但这并没有解决问题,我也尝试用 Console.Read()
处理 UpdateMenu
里面的所有东西但是控制台似乎卡住了.
请注意,只有当我 运行 我在 linux supervisor 中的脚本不使用 dotnet AppRazen.dll
本质上,我 运行 使用这样的 systemd
服务来编写脚本:
[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
老实说,我不知道该如何解决。有人有什么想法吗?
提前致谢。
做你想做的事情的简短回答是你根本做不到。
想一想:您正在尝试创建一个交互式程序(用户可以通过键盘与之交互)。但是您还使它成为守护进程(守护进程 运行 处于后台并且不直接与用户交互)。这是两个相互矛盾的目标。
当 systemd
(或 supervisord
,或 upstart
或任何系统服务程序)运行将您的应用程序作为服务时,它不会提供一种与用户交互的方式,因为这些应用程序希望成为守护进程 - 这意味着用户无法与它们交互。
所以,问问自己你想做什么:你想不想做一个互动程序?如果你想制作一个交互式程序,你不能 运行 通过主管。 运行 直接通过 dotnet /path/to/your.dll
.
其他评论:
ReadKey
可能有问题,但肯定不是你正在干的常见情况,这似乎是 Linux 对 x86_64。OmniSharp 是 IDEs/text-editors 的一个插件,可以简化开发。它提供自动完成和实时语法突出显示。当您 运行 应用程序时,它不涉及。