Klawisze funkcyjne w konsoli

0

Napisałem w konsoli taki prosty program do testowania klawiatury:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int WorkCounter = 0;
            string LastChar = "";
            Console.WriteLine("START");
            while (WorkCounter < 4)
            {
                ConsoleKeyInfo CKI = Console.ReadKey(true);
                Console.Write("    Name: " + CKI.Key.ToString());
                Console.Write("    Code: " + ((int)CKI.KeyChar).ToString());
                if (CKI.KeyChar > 32)
                {
                    Console.Write("    Char: " + CKI.KeyChar.ToString());
                }
                Console.Write("    Shift: " + CKI.Modifiers.HasFlag(ConsoleModifiers.Shift).ToString());
                Console.Write("    Ctrl: " + CKI.Modifiers.HasFlag(ConsoleModifiers.Control).ToString());
                Console.Write("    Alt: " + CKI.Modifiers.HasFlag(ConsoleModifiers.Alt).ToString());
                Console.WriteLine();
                WorkCounter++;
                string KeyId = "{" + ((int)CKI.KeyChar).ToString() + "}{" + CKI.Key.ToString() + "}";
                if (LastChar != KeyId)
                {
                    WorkCounter = 0;
                    LastChar = KeyId;
                }
            }
            Console.WriteLine("STOP");
        }
    }
}

Jak widać, program wyświetla nazwę i numer znaku naciśniętego klawisza, a także zastosowane modyfikatory. Pięciokrotne naciśniecie tego samego klawisza kończy program. Tak naprawdę utworzyłem dwa identyczne programy, jeden jako .NET Framework 4.5, drugi jako .NET Core 3.1, jednakże w obu programach jest identyczny problem.

Programy skompilowałem w Visual Studio na Windows 10, a uruchamiam na Ubuntu Linux 20.04. Problem dotyczy klawiszy funkcyjnych od F1 do F10 oraz bloku zawierającego Ins,Del,Home,End,PgUp,PgDown (nie wiem, czy ten blok ma jakąś nazwę, będę pisać "blok Home/End" bo z tymi dwoma klawiszami jest największy problem).

Jeżeli program uruchamiam lokalnie, to działa prawidłowo, czyli pokazuje ten klawisz, jaki nacisnę. Jak połączę się lokalnie od siebie do siebie (localhost) zarówno po telnet, jak i po ssh, to program również działa prawidłowo.

Natomiast, jak się połączę z innego komputera z Windows, za pomocą PuTTY, to jest problem. W tym przypadku nie ma znaczenia, czy połączę się po SSH, czy po Telnet, a także nie ma znaczenia, czy uruchomię wersję dla net Framework, czy dla Net Core.

Problem polega na tym, ze w domyślnej konfiguracji, program Midnight Commander prawidłowo reaguje na wszystkie klawisze funkcyjne i z bloku HomeEnd. Natomiast mój program, którego kod wrzuciłem, dla klawiszy F1-F4 reaguje tak, jakbym wcisnął kolejno Esc, cyfrę 1, cyfrę numeru klawisza (np. dla F3 będzie to "3") i tyldę. Dla Home w wersji Core leci Esc, 1 i ~, dla End leci Esc, 4, ~. Dla wersji .NET leci odpowiednio 1 i 4 Pozostałe klawisze z bloku HomeEnd interpretuje prawidłowo.

Jak w konfiguracji zmienię klawisze funkcjyjne na "Xterm R6" (domyslnie było ESC[n~), to wszystkie klawisze funkcyjne działają prawidłowo, ale Home/End cały czas ma problem. Ale oczywiście MidNight Commander również działa prawidłowo.

Czy problem jest w samym programie (muszę coś skonfigurować lub doimplementować), czy w konfiguracji serwera Telnet/SSH czy w konfiguracji PuTTY? Jak to jest, że Midnight Commander prawidłowo interpretuje klawisze, a mój program już nie?

1

Praca w terminalu uniksowym / linuksowy to dokladnie jest tak, jak piszesz.

Esc coś ...
Po zalogowaniu do linuxa dostajesz zmienna środowiska TERM=ansi albo TERM=vt60 itd i na tej podstawie warstwa systemu operacyjnego podaje sekwencji Esc coś ...
Konsola linux, ta niby natywna (na znakowym środowisku), też taka jest. Można poczytać man termcap, man curses i kilka innych

a) zakładajmy, ze jest zrobiona maksymalnie dobrze - emulacje terminali maja jakies niedostaki
b) klient o ile na zdalnym polączeniu terminalowym jest na innym hoscie, i nie ma w ogóle mowy by wykonał kod tam, gdzie wykonywany jest proces "wykonawczy", tak w przypadku konsoli "natywnej" jest to ten sam host. Nie znam się czy rzeczywiście zachodzii komunikowanie się procesu terminala z procesem "wykonawczym", ale jest to możliwe.
Np klawisze ALt działają odmiennie.

Nie tylko twój program, ale wspomniany MC tez ma drobne różnice jak pracuje w natywnym terminalu a zdalnym

0

Obecnie, najczęściej stosuje się TERM=xterm, tak domyślnie są konfigurowane TeraTerm i PuTTY. Może być też TERM=vt100 lub TERM=ansi.

Trafiłem na to: link

Okazuje się, że wystarczy wywołać infocmp xterm i poszukać w tym tekście sekwencji dla khome i kend. Okazuje się, że są to odpowiednio "ESC O H" i "ESC O F".

Posiadam też autorski program będący prymitywnym klientem Telnet. W tym programie w kodzie źródłowym własnie zmieniłem funkcjonowanie klawiszy Home i End, aby wysyłały właśnie takie, czyli "ESC O H" i "ESC O F", bo wysyłał "ESC [ 1 ~" i "ESC [ 4 ~" (bo gdzieś tak wyczytałem).

Po tej modyfikacji, jak swoim programem podłączyłem się do localhost po telnet, to w po uruchomieniu testera klawiszy umieszczonego w pierwszym poście, klawisze Home i End były interpretowane prawidłowo.

Natomiast dla TERM=ansi klawisz Home udało się "uruchomić" podobną metodą (jednakże wtedy musi być sekwencja "ESC [ H"), ale klawisza End nie udało się. Czyli poprzez dostosowanie klienta do serwera można.

Tylko, jak zmusić PuTTY, aby też dobrze działał?

1 użytkowników online, w tym zalogowanych: 0, gości: 1