Condividi tramite


API della console classica e sequenze di terminale virtuale

È consigliabile sostituire l'API console di Windows classica con sequenze di terminale virtuale. Questo articolo illustra la differenza tra i due e illustra i motivi della raccomandazione.

Definizioni

La superficie dell'API console di Windows classica è definita come la serie di interfacce funzionali del linguaggio C in kernel32.dll con "Console" nel nome.

Le sequenze di terminale virtuale sono definite come linguaggio di comandi incorporati nei flussi di input standard e di output standard. Le sequenze di terminale virtuale usano caratteri di escape non stampabili per segnalare comandi intrecciati con testo normale stampabile.

Cronologia

La console di Windows offre un'ampia superficie API per le applicazioni della riga di comando client per modificare sia il buffer di visualizzazione dell'output che il buffer di input dell'utente. Tuttavia, altre piattaforme non Windows non hanno mai permettersi questo approccio specifico basato sulle API per i propri ambienti da riga di comando, scegliendo invece di usare sequenze di terminale virtuali incorporate all'interno dei flussi di input standard e di output standard. Per un certo periodo di tempo, Microsoft ha supportato questo comportamento anche nelle prime edizioni di DOS e Windows tramite un driver denominato ANSI.SYS.

Al contrario, le sequenze di terminale virtuale (in un'ampia gamma di dialetti) determinano le operazioni dell'ambiente della riga di comando per tutte le altre piattaforme. Queste sequenze sono radicate in un ECMA Standard e in una serie di estensioni da parte di molti fornitori, fino a risalire ai terminali Digital Equipment Corporation e Tektronix, fino a quelli software più moderni e comuni, come xterm. Molte estensioni esistono all'interno del dominio della sequenza di terminale virtuale e alcune sequenze sono più ampiamente supportate rispetto ad altre, ma è sicuro dire che il mondo ha standardizzato su questo come linguaggio di comando per le esperienze della riga di comando con un subset noto supportato praticamente da ogni terminale e applicazione client da riga di comando.

Supporto multipiattaforma

Le sequenze di terminale virtuale sono supportate in modo nativo tra piattaforme, rendendo facilmente portabili applicazioni terminal e utilità della riga di comando tra versioni e varianti dei sistemi operativi, ad eccezione di Windows.

Al contrario, le API della console di Windows sono supportate solo in Windows. Una libreria di adattatori o traduzioni estesa deve essere scritta tra Windows e terminale virtuale o viceversa, quando si tenta di convertire le utilità della riga di comando da una piattaforma o un'altra.

Accesso remoto

Le sequenze di terminale virtuale hanno un vantaggio importante per l'accesso remoto. Non richiedono alcun lavoro aggiuntivo per il trasferimento o l'esecuzione di chiamate di procedura remota, rispetto a quanto richiesto per configurare una connessione standard da riga di comando remota. È sufficiente connettere un canale di trasporto in uscita e un canale di trasporto in ingresso (o un singolo canale bidirezionale) su una pipe, un socket, un file, una porta seriale o qualsiasi altro dispositivo per trasportare completamente tutte le informazioni necessarie per un'applicazione che parla di queste sequenze a un host remoto.

Al contrario, le API console di Windows sono state accessibili solo nel computer locale e tutti gli sforzi per la loro remoto richiederebbero la creazione di un intero livello di chiamata remota e interfaccia di trasporto oltre un semplice canale.

Separazione delle problematiche

Alcune API della console di Windows offrono accesso di basso livello ai buffer di input e output o alle funzioni utili per le righe di comando interattive. Ciò potrebbe includere alias e cronologia dei comandi programmati all'interno del sottosistema della console e dell'ambiente host, anziché all'interno dell'applicazione client della riga di comando stessa.

Al contrario, altre piattaforme affidano la memorizzazione dello stato corrente dell'applicazione e le funzionalità di convenienza alla responsabilità dell'utilità della riga di comando o della shell stessa.

Il modo di gestire questa responsabilità nell'host e nell'API della console di Windows semplifica la scrittura di un'applicazione da riga di comando con queste funzionalità, rimuovendo la responsabilità di ricordare lo stato del disegno o gestire le funzionalità di praticità di modifica. Tuttavia, ciò rende quasi impossibile connettere tali attività in modalità remota tra piattaforme, versioni o scenari a causa di variazioni nelle implementazioni e nella disponibilità. Questo modo di gestire la responsabilità rende anche l'esperienza interattiva finale di queste applicazioni della riga di comando di Windows completamente dipendenti dall'implementazione, dalle priorità e dal ciclo di rilascio dell'host della console.

Ad esempio, le funzionalità avanzate di modifica della riga, come l'evidenziazione della sintassi e la selezione complessa, sono possibili solo quando un'applicazione della riga di comando gestisce i problemi di modifica. La console non può mai avere un contesto sufficiente per comprendere completamente questi scenari in modo ampio, come l'applicazione client.

Al contrario, altre piattaforme usano sequenze di terminale virtuale per gestire queste attività e la comunicazione del terminale virtuale stesso tramite librerie lato client riutilizzabili, ad esempio readline e ncurses. Il terminale finale è responsabile solo della visualizzazione delle informazioni e della ricezione dell'input tramite tale canale di comunicazione bidirezionale.

Wrong-Way Verbi

Con la console di Windows, alcune azioni possono essere eseguite nella direzione opposta a quella naturale sui flussi di input e output. Ciò consente alle applicazioni della riga di comando di Windows di evitare il problema di gestire i propri buffer. Consente anche alle app della riga di comando di Windows di eseguire operazioni avanzate, ad esempio simulare/inserire input per conto di un utente o leggere una parte della cronologia di ciò che è stato scritto.

Sebbene ciò fornisca potenza aggiuntiva alle applicazioni Windows che operano in un contesto utente specifico su un unico computer, fornisce anche un vettore per attraversare livelli di sicurezza e privilegi o domini quando vengono usati in determinati scenari. Tali scenari includono il funzionamento fra contesti nello stesso computer o fra contesti su un altro computer o ambiente.

Altre piattaforme, che usano sequenze di terminale virtuale, non consentono questa attività. Lo scopo del nostro consiglio di passare dalla console di Windows classica alle sequenze di terminale virtuale consiste nel convergere con questa strategia sia per motivi di interoperabilità che di sicurezza.

Accesso diretto alla finestra

La superficie dell'API console di Windows fornisce l'handle della finestra esatto alla finestra di hosting. Ciò consente a un'utilità della riga di comando di eseguire operazioni di finestra avanzate raggiungendo l'ampia gamma di API Win32 consentite su un handle di finestra. Queste API Win32 possono modificare lo stato della finestra, il frame, l'icona o altre proprietà sulla finestra.

Al contrario, in altre piattaforme con sequenze di terminale virtuale è presente un set ristretto di comandi che possono essere eseguiti sulla finestra. Questi comandi possono eseguire operazioni come la modifica delle dimensioni della finestra o del titolo visualizzato, ma devono essere eseguite nella stessa banda e sotto lo stesso controllo del resto del flusso.

Man mano che Windows si è evoluto, i controlli di sicurezza e le restrizioni sugli handle di finestra sono aumentati. Inoltre, la natura e l'esistenza di un handle di finestra indirizzabile tramite applicazione su qualsiasi elemento specifico dell'interfaccia utente si è evoluta, soprattutto con il crescente supporto dei fattori di forma dei dispositivi e delle piattaforme. Ciò rende fragile l'accesso diretto delle finestre alle applicazioni da riga di comando man mano che la piattaforma e le esperienze si evolvono.

Unicode

UTF-8 è la codifica accettata per i dati Unicode in quasi tutte le piattaforme moderne, in quanto colpisce il giusto equilibrio tra portabilità, dimensioni di archiviazione e tempo di elaborazione. Tuttavia, Windows ha storicamente scelto UTF-16 come codifica principale per i dati Unicode. Il supporto per UTF-8 aumenta in Windows e l'uso di questi formati Unicode non impedisce l'utilizzo di altre codifiche.

La piattaforma Console di Windows è supportata e continuerà a supportare tutte le tabelle codici e le codifiche esistenti. Usare UTF-16 per garantire la massima compatibilità tra le versioni di Windows ed eseguire la traduzione algoritmica con UTF-8, se necessario. L'aumento del supporto di UTF-8 è in corso per il sistema console.

Il supporto UTF-16 nella console può essere usato senza alcuna configurazione aggiuntiva tramite la variante W di tutte le API della console ed è una scelta più probabile per le applicazioni già ben note in UTF-16 tramite la comunicazione con la wchar_t variante W di altre funzioni e prodotti della piattaforma Microsoft e Windows.

Il supporto UTF-8 nella console può essere usato tramite la variante A delle API console per gli handle della console dopo aver impostato la tabella codici su 65001 o CP_UTF8 con i metodi SetConsoleOutputCP e SetConsoleCP , a seconda delle esigenze. L'impostazione delle tabelle codici in anticipo è necessaria solo se il computer non ha scelto "Usa Unicode UTF-8 per il supporto linguistico mondiale" nelle impostazioni per le applicazioni non Unicode nella sezione Area del Pannello di controllo.

Annotazioni

A partire dal momento, UTF-8 è supportato completamente nel flusso di output standard con i metodi WriteConsole e WriteFile . Il supporto nel flusso di input varia a seconda della modalità di input e continuerà a migliorare nel tempo. In particolare, le modalità predefinite "cucinate" sull'input non supportano ancora completamente UTF-8. Lo stato corrente di questo lavoro è disponibile in microsoft/terminal#7777 su GitHub. La soluzione alternativa consiste nell'usare UTF-16 traducibile in modo algoritmico per la lettura dell'input tramite ReadConsoleW o ReadConsoleInputW fino a quando non vengono risolti i problemi in sospeso.

Consigli

Per tutti gli sviluppi nuovi e in corso in Windows, le sequenze di terminale virtuale sono consigliate come modalità di interazione con il terminale. Questo convergerà le applicazioni client della riga di comando di Windows con lo stile di programmazione delle applicazioni su tutte le altre piattaforme.

Eccezioni per l'uso delle API della console di Windows

Per stabilire l'ambiente iniziale è comunque necessario un subset limitato di API della console di Windows . La piattaforma Windows è ancora diversa da altre nel processo, nel segnale, nel dispositivo e nella gestione della codifica:

  • Gli handle standard per un processo verranno comunque controllati con GetStdHandle e SetStdHandle.

  • La configurazione delle modalità della console in un handle per acconsentire esplicitamente al supporto della sequenza di terminale virtuale verrà gestita con GetConsoleMode e SetConsoleMode.

  • La dichiarazione di codice o supporto UTF-8 viene eseguita con i metodi SetConsoleOutputCP e SetConsoleCP .

  • È possibile che sia necessario un certo livello di gestione complessiva dei processi con AllocConsole, AttachConsole e FreeConsole per partecipare o lasciare una sessione del dispositivo console.

  • I segnali e la gestione dei segnali continueranno a essere eseguiti con SetConsoleCtrlHandler, HandlerRoutine e GenerateConsoleCtrlEvent.

  • La comunicazione con gli handle del dispositivo console può essere eseguita con WriteConsole e ReadConsole. Questi possono essere sfruttati anche tramite i runtime del linguaggio di programmazione nelle forme di: - C Runtime (CRT): I/O di flusso come printf, scanf, putc, getc o altri livelli di funzioni di I/O. - Libreria standard C++ (STL): iostream come cout e cin. - Runtime .NET: System.Console come Console.WriteLine.

  • Le applicazioni che devono essere consapevoli delle modifiche delle dimensioni della finestra dovranno comunque usare ReadConsoleInput per riceverle interleaved con gli eventi chiave, perché ReadConsole solo li scarterà.

  • La ricerca delle dimensioni della finestra deve comunque essere eseguita con GetConsoleScreenBufferInfo per le applicazioni che tentano di disegnare colonne, griglie o riempire la visualizzazione. Le dimensioni della finestra e del buffer corrispondono in una sessione di pseudoconsole .

Pianificazione futura e pseudoconsole

Non sono previsti piani per rimuovere le API della console di Windows dalla piattaforma.

Al contrario, l'host della console di Windows ha fornito la tecnologia pseudoconsole per convertire le chiamate dell'applicazione della riga di comando di Windows esistenti in sequenze di terminale virtuali e inoltrarle a un altro ambiente di hosting in modalità remota o tra piattaforme.

Questa traduzione non è perfetta. Richiede che la finestra host della console mantenga un ambiente simulato di ciò che Windows avrebbe visualizzato all'utente. Proietta quindi una replica di questo ambiente simulato nell'host pseudoconsole . Tutte le chiamate API della console di Windows vengono gestite all'interno dell'ambiente simulato per soddisfare le esigenze dell'applicazione client della riga di comando legacy. Solo gli effetti vengono propagati nell'host finale.

Un'applicazione da riga di comando che desie la piena compatibilità tra piattaforme e il supporto completo di tutte le nuove funzionalità e scenari sia in Windows che altrove è quindi consigliabile passare alle sequenze di terminale virtuali e regolare l'architettura delle applicazioni da riga di comando per allinearsi a tutte le piattaforme.

Altre informazioni su questa transizione di Windows per le applicazioni da riga di comando sono disponibili nella roadmap dell'ecosistema.