Compartir a través de


API de consola clásica frente a secuencias de terminal virtual

Nuestra recomendación es reemplazar la API de consola de Windows clásica por secuencias de terminal virtual. En este artículo se describirá la diferencia entre los dos y se describen los motivos de nuestra recomendación.

Definiciones

La superficie clásica de la API de consola de Windows se define como la serie de interfaces funcionales del lenguaje C en kernel32.dll con "Consola" en el nombre.

Las secuencias de terminal virtual se definen como un lenguaje de comandos incrustados en los flujos de entrada y salida estándar. Las secuencias de terminal virtual usan caracteres de escape no imprimibles para indicar comandos intercalados con texto imprimible normal.

Historia

La consola de Windows proporciona una amplia superficie de API para que las aplicaciones de línea de comandos de cliente manipulen tanto el búfer de visualización de salida como el búfer de entrada del usuario. Sin embargo, otras plataformas que no son de Windows nunca han proporcionado este enfoque específico basado en API a sus entornos de línea de comandos, eligiendo en su lugar usar secuencias de terminal virtual insertadas dentro de los flujos de entrada y salida estándar. (Durante un tiempo, Microsoft también soportó este comportamiento en las primeras ediciones de DOS y Windows a través de un controlador llamado ANSI.SYS).

Por el contrario, las secuencias de terminal virtual (en una variedad de dialectos) impulsan las operaciones de entorno de la línea de comandos para todas las demás plataformas. Estas secuencias se basan en un ECMA Standard y una serie de extensiones por parte de muchos proveedores, que se remontan a terminales de Digital Equipment Corporation y Tektronix, pasando por terminales de software más modernos y populares, como xterm. Existen muchas extensiones en el dominio de la secuencia de terminales virtual, y algunas secuencias se admiten más ampliamente que otras, pero se puede afirmar con seguridad que se ha estandarizado mundialmente como el lenguaje de comandos para las experiencias de línea de comandos con un subconjunto conocido que es compatible prácticamente con todos los terminales y aplicaciones cliente de línea de comandos.

Compatibilidad multiplataforma

Las secuencias de terminal virtual se admiten de forma nativa entre plataformas, lo que hace que las aplicaciones de terminal y las utilidades de línea de comandos sean fácilmente portátiles entre versiones y variaciones de sistemas operativos, con la excepción de Windows.

Por el contrario, las API de consola de Windows solo se admiten en Windows. Se debe escribir un extenso adaptador o biblioteca de traducción entre Windows y el terminal virtual, o viceversa, al intentar portar utilidades de línea de comandos desde una plataforma u otra.

Acceso remoto

Las secuencias de terminal virtual contienen una ventaja importante para el acceso remoto. No requieren trabajo adicional para el transporte ni para realizar llamadas a procedimientos remotos, más allá de lo necesario para configurar una conexión estándar de línea de comandos remota. Simplemente conectar un canal de transporte saliente y un canal de transporte entrante (o un único canal bidireccional) mediante una canalización, un socket, un archivo, un puerto serie u otro dispositivo cualquiera es suficiente para transmitir toda la información necesaria de manera completa para una aplicación que maneja estas secuencias a un host remoto.

Por el contrario, las API de consola de Windows solo han sido accesibles en el equipo local y todos los esfuerzos para realizar la administración remota de ellos requerirían crear una capa completa de interfaz de transporte y llamadas remotas más allá de un canal simple.

Separación de intereses

Algunas API de consola de Windows proporcionan acceso de bajo nivel a los búferes de entrada y salida o funciones útiles para las líneas de comandos interactivas. Esto puede incluir alias y historial de comandos programados dentro del subsistema de consola y el entorno host, en lugar de dentro de la propia aplicación cliente de línea de comandos.

Por el contrario, otras plataformas hacen que la memoria del estado actual de la aplicación y la funcionalidad de conveniencia sean responsabilidad de la propia utilidad de línea de comandos o shell.

La manera en que la Consola de Windows maneja esta responsabilidad en el host y la API de la Consola hace que escribir una aplicación de línea de comandos con estas características sea más rápido y sencillo, removiendo la carga de recordar el estado de dibujo o manejar características que faciliten la edición. Sin embargo, esto hace que sea casi imposible conectar esas actividades de forma remota entre plataformas, versiones o escenarios debido a variaciones en implementaciones y disponibilidad. Esta forma de controlar la responsabilidad también hace que la experiencia interactiva final de estas aplicaciones de línea de comandos de Windows dependa completamente de la implementación, las prioridades y el ciclo de lanzamiento del host de consola.

Por ejemplo, las características avanzadas de edición de líneas, como el resaltado de sintaxis y la selección compleja, solo son posibles cuando una aplicación de línea de comandos controla los problemas de edición. La consola nunca podría tener suficiente contexto para comprender completamente estos escenarios de una manera amplia, como la aplicación cliente.

Por el contrario, otras plataformas usan secuencias de terminal virtual para controlar estas actividades y la comunicación de terminal virtual a través de bibliotecas reutilizables del lado cliente, como readline y ncurses. El terminal final solo es responsable de mostrar información y recibir la entrada a través de ese canal de comunicación bidireccional.

Verbos con dirección incorrecta

Con la consola de Windows, algunas acciones se pueden realizar en la dirección opuesta a natural en los flujos de entrada y salida. Esto permite que las aplicaciones de línea de comandos de Windows eviten la preocupación de administrar sus propios búferes. También permite que las aplicaciones de línea de comandos de Windows realicen operaciones avanzadas, como simular o insertar entradas en nombre de un usuario, o leer parte del historial de lo que se escribió.

Aunque esto proporciona energía adicional a las aplicaciones de Windows que funcionan en un contexto de usuario específico en una sola máquina, también proporciona un vector para cruzar los niveles de seguridad y privilegios o dominios cuando se usan en determinados escenarios. Estos escenarios incluyen el funcionamiento entre contextos en la misma máquina o entre contextos en otra máquina o entorno.

Otras plataformas, que usan secuencias de terminal virtual, no permiten esta actividad. La intención de nuestra recomendación para pasar de la consola clásica de Windows a las secuencias de terminal virtual consiste en converger con esta estrategia tanto por motivos de interoperabilidad como de seguridad.

Acceso directo a ventanas

La interfaz de la API de consola de Windows proporciona el identificador de ventana exacto a la ventana anfitriona. Esto permite que una utilidad de línea de comandos realice operaciones de ventana avanzadas mediante el uso de la amplia gama de APIs de Win32 aplicadas a un identificador de ventana. Estas API de Win32 pueden manipular el estado de la ventana, el marco, el icono u otras propiedades sobre la ventana.

Por el contrario, en otras plataformas con secuencias de terminal virtual, hay un conjunto estrecho de comandos que se pueden realizar en la ventana. Estos comandos pueden hacer cosas como cambiar el tamaño de la ventana o el título mostrado, pero deben realizarse en la misma banda y bajo el mismo control que el resto de la secuencia.

A medida que Windows ha ido evolucionando, los controles de seguridad y las restricciones sobre los identificadores de ventana han aumentado. Además, la naturaleza y la existencia de un identificador de ventana direccionable por la aplicación en cualquier elemento específico de la interfaz de usuario ha evolucionado, especialmente con la mayor compatibilidad de los factores de forma y las plataformas de los dispositivos. Esto hace que el acceso directo a las ventanas de las aplicaciones de línea de comandos sea frágil a medida que evoluciona la plataforma y las experiencias.

Unicode

UTF-8 es la codificación aceptada para los datos Unicode en casi todas las plataformas modernas, ya que tiene el equilibrio adecuado entre la portabilidad, el tamaño de almacenamiento y el tiempo de procesamiento. Sin embargo, Windows eligió históricamente UTF-16 como su codificación principal para los datos Unicode. La compatibilidad con UTF-8 aumenta en Windows y el uso de estos formatos Unicode no impide el uso de otras codificaciones.

La plataforma de consola de Windows es compatible y seguirá admitiendo todas las páginas de códigos y codificaciones existentes. Use UTF-16 para obtener la máxima compatibilidad entre versiones de Windows y realizar la traducción algorítmica con UTF-8 si es necesario. El aumento de la compatibilidad con UTF-8 está en curso para el sistema de consola.

La compatibilidad con UTF-16 en la consola se puede usar sin ninguna configuración adicional a través de la variante W de todas las API de consola y es una opción más probable para las aplicaciones que ya están bien versadas en UTF-16 a través de la comunicación con y la wchar_t variante W de otras funciones y productos de la plataforma Microsoft y Windows.

La compatibilidad con UTF-8 en la consola se puede activar mediante la variante A de las API de consola en los identificadores de consola, después de establecer la página de códigos a 65001 o CP_UTF8 con los métodos SetConsoleOutputCP y SetConsoleCP, según corresponda. Establecer las páginas de códigos de antemano solo es necesario si la máquina no ha elegido "Usar UTF-8 Unicode para la compatibilidad con idiomas en todo el mundo" en la configuración de aplicaciones que no son Unicode en la sección Región del Panel de control.

Nota:

A partir de ahora, UTF-8 se admite completamente en el flujo de salida estándar con los métodos WriteConsole y WriteFile . La compatibilidad con el flujo de entrada varía en función del modo de entrada y seguirá mejorando con el tiempo. En particular, los modos predeterminados "cooked" en la entrada aún no admiten UTF-8. El estado actual de este trabajo se puede encontrar en microsoft/terminal#7777 en GitHub. La solución alternativa es usar el UTF-16 traducible de forma algorítmica para leer la entrada a través de ReadConsoleW o ReadConsoleInputW hasta que se resuelvan los problemas pendientes.

Recomendaciones

Para todo el desarrollo nuevo y continuo en Windows, se recomiendan secuencias de terminal virtual como forma de interactuar con el terminal. Esto alineará las aplicaciones cliente de línea de comandos de Windows con la forma de programar aplicaciones en todas las demás plataformas.

Excepciones para usar las API de consola de Windows

Todavía es necesario un subconjunto limitado de las API de consola de Windows para establecer el entorno inicial. La plataforma Windows sigue siendo diferente de otras en el proceso, la señal, el dispositivo y el control de codificación:

  • Los identificadores estándar de un proceso continuarán siendo controlados mediante GetStdHandle y SetStdHandle.

  • La configuración de los modos de la consola en un identificador para lograr la compatibilidad con la secuencia de terminal virtual se administrará con GetConsoleMode y SetConsoleMode.

  • La declaración de compatibilidad con páginas de códigos o UTF-8 se realiza con los métodos SetConsoleOutputCP y SetConsoleCP.

  • Es posible que se requiera algún nivel de administración general de procesos con AllocConsole, AttachConsole y FreeConsole para unirse o dejar una sesión de dispositivo de consola.

  • Las señales y el control de señales se seguirán llevando a cabo con SetConsoleCtrlHandler, HandlerRoutine y GenerateConsoleCtrlEvent.

  • La comunicación con los identificadores de dispositivo de consola se puede realizar con WriteConsole y ReadConsole. También se pueden aprovechar a través de los entornos de ejecución del lenguaje de programación en forma de: - C Runtime (CRT): E/S de flujo como printf, scanf, putc, getc u otros niveles de funciones de E/S. - Biblioteca estándar de C++ (STL): iostream como cout y cin. - Runtime de .NET: System.Console como Console.WriteLine.

  • Las aplicaciones que deben tener en cuenta los cambios de tamaño de ventana seguirán teniendo que usar ReadConsoleInput para recibirlas intercaladas con eventos clave, ya que ReadConsole solo las descartará.

  • La búsqueda del tamaño de la ventana todavía debe realizarse con GetConsoleScreenBufferInfo para las aplicaciones que intentan dibujar columnas, cuadrículas o rellenar la pantalla. El tamaño de la ventana y del búfer será equivalente en una sesión de pseudoconsola.

Planeación futura y pseudoconsola

No hay planes para quitar las API de consola de Windows de la plataforma.

Por el contrario, el host de la consola de Windows ha proporcionado la tecnología de pseudoconsola para traducir las llamadas existentes de la aplicación de línea de comandos de Windows a secuencias de terminal virtual y reenviarlas a otro entorno de hospedaje de forma remota o entre plataformas.

Esta traducción no es perfecta. Requiere la ventana de la consola anfitriona para poder mantener un entorno simulado de lo que Windows habría mostrado al usuario. A continuación, proyecta una réplica de este entorno simulado en el host de pseudoconsola . Todas las llamadas a la API de consola de Windows se operan dentro del entorno simulado para satisfacer las necesidades de la aplicación cliente de línea de comandos heredada. Solo se propagan los efectos al host final.

Por lo tanto, se recomienda una aplicación de línea de comandos que desee una compatibilidad completa entre las plataformas y la compatibilidad total de todas las nuevas características y escenarios tanto en Windows como en otros lugares para pasar a secuencias de terminal virtual y ajustar la arquitectura de las aplicaciones de línea de comandos para alinearse con todas las plataformas.

Puede encontrar más información sobre esta transición de Windows para aplicaciones de línea de comandos en nuestra hoja de ruta del ecosistema.