Construir menús TUI en PowerShell con Terminal.Gui

Última actualización: 17/12/2025
Autor: Isaac
  • Terminal.Gui permite crear interfaces TUI avanzadas en PowerShell, con menús, diálogos y tablas en modo texto.
  • Un módulo bien diseñado puede incluir binarios para .NET Core y .NET Framework y cargarlos dinámicamente según la versión de PowerShell.
  • Funciones como ConvertTo-DataTable, RefreshTable o ShowWhatIf facilitan la construcción de aplicaciones TUI completas y seguras.
  • Con estos patrones, la misma solución TUI puede ejecutarse tanto en Windows PowerShell como en PowerShell 7 sin cambios en la lógica principal.

Interfaz TUI en PowerShell con Terminal.Gui

Si trabajas a diario con scripts y automatización, tarde o temprano te apetece salir un poco de la típica consola en blanco y negro. Crear menús TUI (Text User Interface) en PowerShell con la librería Terminal.Gui te permite montar interfaces “tipo aplicación” directamente en la terminal, con cuadros de diálogo, tablas, formularios e incluso ventanas modales, sin recurrir a WinForms ni WPF.

En este artículo vas a ver, de forma muy detallada, cómo llevar estas interfaces TUI tanto a PowerShell 7 como a Windows PowerShell clásico, cómo cargar correctamente los binarios según la versión, y cómo sacar partido a controles avanzados como diálogos de credenciales, tablas o cuadros de mensaje. También repasaremos un conjunto de funciones de ejemplo para gestionar datos desde una TUI, que te servirán como plantilla para tus propios proyectos.

Qué es Terminal.Gui (gui.cs) y por qué usarlo con PowerShell

Terminal.Gui, conocido también como gui.cs, es un framework .NET para crear interfaces de texto que funcionan en la consola. No muestra ventanas gráficas “clásicas”, sino interfaces en modo texto, pero con menús, botones, cuadros de texto, tablas, diálogos de confirmación, etc., perfectamente navegables con teclado.

De serie, la librería se ha venido compilando solo para .NET Core, lo que encaja con PowerShell 7. Esto deja fuera a Windows PowerShell (las versiones 5.1 y anteriores), que usan el .NET Framework clásico. El resultado es que muchos ejemplos que ves por ahí solo funcionan en PS 7 y fallan en la consola tradicional de Windows.

La clave está en que no hay una limitación técnica real que impida usar Terminal.Gui en Windows PowerShell. El problema es únicamente de compilación: los binarios oficiales se generan contra .NET Core, pero la misma base de código puede compilarse también para .NET Framework sin cambios de peso.

Para cubrir este hueco, se puede crear un módulo que incluya dos versiones del ensamblado Terminal.Gui: una para .NET Core y otra para .NET Framework. El módulo TuiCredential es un ejemplo perfecto de este enfoque, porque encapsula todo el trabajo de compilación y carga dinámica de los DLLs para que tú solo tengas que llamar a un cmdlet.

Ejemplo de menú TUI en PowerShell

Hacer que TUI funcione en PowerShell 7 y en Windows PowerShell

Para disponer de Terminal.Gui tanto en Windows PowerShell como en PowerShell 7, lo que necesitas es un juego de binarios para cada runtime. Es decir, un ensamblado compilado contra .NET Framework y otro contra .NET Core. El módulo TuiCredential empaqueta ambos dentro de su estructura de carpetas.

Una vez tienes el módulo publicado (o descargado desde la PowerShell Gallery), el proceso de instalación es muy simple. Basta con usar el cmdlet oficial para módulos:

Install-Module -Name TuiCredential -Scope CurrentUser

Este comando se puede ejecutar tanto en Windows PowerShell como en PowerShell 7. La magia está en que el módulo lleva dentro los DLL adecuados y un script de inicialización que decide cuál cargar según la versión en la que estés trabajando. De esta forma, el mismo código TUI funciona en ambas plataformas sin que tengas que duplicar lógica.

El punto clave del módulo es un archivo de arranque (por ejemplo, init.ps1) que, al importarse el módulo, se encarga de detectar la versión de PowerShell y cargar el ensamblado correcto de Terminal.Gui mediante Add-Type. Así, todos los tipos y clases quedan disponibles para el resto de funciones del módulo.

Carga condicional de binarios con init.ps1

Cuando revisas el árbol de archivos del módulo, verás dos subcarpetas de binarios, típicamente algo como Binaries (para .NET Framework) y BinariesPs7 (para .NET Core). Ambas contienen distintas compilaciones de Terminal.Gui.dll, orientadas a cada runtime.

Dentro del módulo, el script init.ps1 hace un chequeo muy sencillo con $PSVersionTable.PSVersion.Major para saber dónde estás. Si la versión mayor es menor o igual que 5, asume que trabajas en Windows PowerShell y prepara la ruta a la carpeta de binarios de .NET Framework; en caso contrario, apunta a la carpeta para PowerShell 7 y .NET Core.

El patrón básico es construir una ruta usando Join-Path con $PSScriptRoot, de esta forma el módulo siempre localiza sus DLLs independientemente de dónde lo tengas instalado. Luego se concatena el nombre del ensamblado, como Terminal.Gui.dll, y se llama a Add-Type -Path para cargar el tipo en la sesión.

  Tips on how to Backup Textual content Messages On Android Telephone to Gmail

Además, el script puede escribir mensajes con Write-Verbose para indicar si está cargando binarios .NET Framework o .NET Core. Esto resulta muy útil cuando depuras problemas de compatibilidad, versiones de ensamblados o conflictos de dependencias.

Gracias a este mecanismo de carga bajo demanda, todo el código TUI escrito después del import parte de la certeza de que los tipos de Terminal.Gui ya están disponibles y son compatibles con la versión de PowerShell en uso, lo que evita tener que escribir lógica duplicada o condicional en cada función.

Diálogo de credenciales TUI con TuiCredential

Una vez tienes el módulo TuiCredential instalado y los binarios cargados de forma transparente, la forma más visible de aprovecharlo es mediante el cmdlet Show-CredentialDialog, que muestra un cuadro de diálogo TUI para pedir usuario y contraseña dentro de la terminal.

La llamada más básica se hace así:

Show-CredentialDialog

Al ejecutarlo, aparece en la consola una ventana tipo diálogo, en modo texto, que solicita credenciales. El campo de nombre de usuario viene ya rellenado con el usuario actual de la sesión, y solo tienes que introducir la contraseña y pulsar ENTER. El cmdlet devuelve un objeto PSCredential que puedes usar tal cual para autenticación en otras conexiones, cmdlets remotos, accesos a bases de datos o cualquier otro sistema que requiera credenciales seguras.

El diálogo es configurable mediante parámetros. Por ejemplo, si quieres cambiar el título de la ventana, fijar un nombre de usuario concreto y añadir un botón para alternar el enmascarado de la contraseña, puedes usar algo como:

Show-CredentialDialog -Title 'Log on to File Server 12' -UserName serviceaccount1 -AllowToggle

Con esta variante consigues un diálogo más adaptado al contexto de tu script, ideal cuando necesitas pedir credenciales para un servicio concreto (por ejemplo, una cuenta de servicio de un servidor de ficheros) en lugar de usar siempre el usuario que ha iniciado sesión.

Un vistazo rápido a otras interfaces TUI en PowerShell

Más allá del diálogo de credenciales, Terminal.Gui permite montar aplicaciones completas de consola con menús, formularios, tablas y barras de estado. Un ejemplo práctico es un gestor de “work items” o tareas, construido sobre una base de datos SQLite y controlado desde PowerShell, que utiliza una serie de funciones para refrescar formularios, mostrar ayuda, abrir bases de datos o manejar confirmaciones de acciones.

En este tipo de aplicaciones, es habitual encontrarse con funciones auxiliares para limpiar y reiniciar formularios, actualizar el estado de una barra inferior, mostrar cuadros de mensaje con operaciones tipo WhatIf, o incluso abrir diálogos de selección de archivos con OpenDialog.

También se suele usar una función de utilidad para convertir colecciones de objetos de PowerShell en DataTable, de forma que se puedan enlazar fácilmente a un control TableView de Terminal.Gui. Esto es clave para mostrar listados de datos con columnas, permitir la selección de filas y navegar por registros dentro de la TUI.

Este enfoque de “mini aplicación” en modo texto es muy interesante cuando quieres reemplazar una GUI WinForms pesada por una solución más ligera, portable y amigable con el teclado, manteniendo toda la lógica de negocio en PowerShell y .NET.

Convertir datos de PowerShell a DataTable para TableView

La función ConvertTo-DataTable es una pieza fundamental cuando quieres alimentar un control TableView con datos obtenidos de cmdlets de PowerShell. La idea es tomar objetos genéricos, construir a partir de ellos un System.Data.DataTable y devolverlo como resultado.

Esta función suele declararse con CmdletBinding, OutputType y parámetros que aceptan entrada por canalización. En el bloque Begin, se preparan una lista genérica de objetos y un nuevo DataTable llamado, por ejemplo, PSData. A medida que se van recibiendo elementos en el bloque Process, se añaden a la lista.

Al finalizar, en el bloque End, la función inspecciona las propiedades del primer objeto para definir las columnas del DataTable. Para cada propiedad se crea una columna con el nombre adecuado y el tipo de dato correspondiente. A continuación, se recorre la lista de objetos para ir construyendo filas: cada propiedad se asigna a la columna equivalente, y la fila se añade a la tabla.

Un pequeño truco de PowerShell permite retornar el DataTable como único resultado, en lugar de las filas, usando la sintaxis de coma delante del objeto (, $table). Eso garantiza que el valor devuelto sea el propio DataTable, listo para enlazar con TableView.Table más adelante.

  Formas fáciles de eliminar la contraseña de los archivos PDF protegidos

Para ayudar en depuración, la función puede escribir mensajes con Write-Verbose indicando cuántos elementos se han añadido y qué columnas se están definiendo. Esto te vendrá muy bien cuando cambie el esquema de datos o cuando algo falle al intentar mostrar la tabla en pantalla.

Gestión de formularios TUI: limpiar, reiniciar y rellenar campos

Cuando construyes una interfaz TUI con varios cuadros de texto, listas desplegables, casillas de verificación y etiquetas, es muy práctico agrupar la lógica de mantenimiento del formulario en funciones dedicadas como ClearForm, ResetForm o Populate. Así evitas duplicar código por todos lados.

La función ClearForm suele ocuparse de vaciar los campos de entrada principales (nombre, descripción, progreso, fechas), desmarcar casillas como WhatIf, restaurar valores por defecto (por ejemplo, 30 días de plazo) y reajustar la barra de estado para mostrar la fecha actual y el texto “Ready”. Al final, establece el foco de nuevo en el primer campo y fuerza un Application.Refresh para redibujar la interfaz.

ResetForm va un poco más allá: además de limpiar los campos, también restaura la ruta actual a la base de datos de trabajo, reinicia filtros de la tabla (por ejemplo, una casilla para activar o no un filtrado) y llama a funciones como RefreshCategoryList y RefreshTable para reconstruir el listado principal en pantalla.

Por su parte, Populate toma la fila seleccionada en el TableView y rellena el formulario con los datos de ese elemento: nombre de la tarea, descripción, fecha de vencimiento, categoría y progreso. Según si la tarea está vencida, ajusta la visibilidad de una etiqueta de aviso (OverDue), y también puede mostrar u ocultar una casilla que permite limpiar la descripción rápidamente.

En este proceso también se ajusta la selección de la lista de categorías, localizando el índice apropiado en una lista de soporte (por ejemplo, una List[string] con todas las categorías) y asignándolo al DropDown correspondiente. De esta manera, el formulario refleja de forma coherente la información del registro activo.

Refrescar tablas y listas de categorías en la interfaz

En una aplicación TUI basada en Terminal.Gui, es crítico disponer de mecanismos para actualizar dinámicamente el contenido de la tabla y las listas desplegables. Aquí entran en juego funciones como RefreshTable y RefreshCategoryList, que trabajan mano a mano con cmdlets personalizados que consultan la base de datos.

RefreshTable suele recibir opcionalmente una categoría de filtro. Empieza por limpiar el control TableView usando RemoveAll y Clear para eliminar cualquier rastro de datos antiguo. A continuación, llama a un cmdlet tipo Get-PSWorkItem -Path <ruta> -All y aplica Where-Object para filtrar por la categoría deseada, seleccionando las columnas relevantes (ID, Name, Description, DueDate, Progress, Category, OverDue).

Ese flujo de objetos se pasa por la función ConvertTo-DataTable, que devuelve un DataTable ya listo para enlazar. El resultado se asigna a TableView.Table, estableciendo la fuente de datos de la tabla. Para completar la experiencia, se ajustan estilos de columnas mediante TableView.Style.ColumnStyles.Add, controlando la alineación (por ejemplo, Right para ID o Progress, Justified para DueDate) y el ancho mínimo.

Una vez configurado el estilo, se llama a SetNeedsDisplay para que el control se repinte con la nueva información. Al ejecutar nuevamente RefreshTable después de crear, modificar o eliminar tareas, el usuario ve al instante el estado actualizado, sin tener que reiniciar la aplicación TUI.

RefreshCategoryList, por otro lado, consulta las categorías de trabajo mediante un cmdlet como Get-PSWorkItemCategory -Path <ruta>. De esa salida se extrae la propiedad Category, se ordena y se pasa a SetSource del control desplegable (DropDown o List, según el diseño). Además, se construye una lista genérica de cadenas que actúa como tabla de búsqueda para localizar rápidamente el índice de una categoría concreta.

Es habitual también generar un pequeño informe resumen con Get-PSWorkItemReport, formateándolo con Format-Table Category, Count, PctTotal y Output-String. El texto resultante se asigna a una etiqueta en la interfaz, ofreciendo de un vistazo un desglose de cuántas tareas hay por categoría y qué porcentaje suponen del total.

Diálogos de ayuda, información y selección de base de datos

Para redondear la usabilidad de una TUI en PowerShell, conviene añadir diálogos auxiliares para mostrar ayuda, información de la aplicación y para seleccionar archivos de base de datos. Con Terminal.Gui esto se consigue de forma bastante directa.

  Usar Git desde PowerShell con credenciales seguras: métodos, trucos y solución de problemas

La función ShowHelp, por ejemplo, construye un cuadro de diálogo a partir del contenido de Get-Help de un cmdlet concreto (como Open-PSWorkItemConsole). Toma la descripción del cmdlet, la pasa a Out-String y la usa como texto del diálogo. Luego crea un objeto Dialog con título, ancho, alto y alineación, le añade un botón “OK” (un Terminal.Gui.Button con evento Add_Clicked que cierra el diálogo) y ejecuta Application.Run sobre él.

Para mostrar información de versión y dependencias, ShowAbout recopila datos de varias ensamblados usando System.Reflection.Assembly.GetAssembly(…).GetName().Version. Suele incluir la versión de PSWorkItem, la de PowerShell, la de Terminal.Gui, la de NStack y la de System.Data.SQLite. Con eso monta una cadena formateada y lanza un MessageBox.Query con título de “About” y un único botón “Ok”.

La selección de la base de datos de trabajo se hace con la función OpenDatabase, que instancia un OpenDialog de Terminal.Gui, configurando CanChooseDirectories, CanChooseFiles y AllowsMultipleSelection acorde a lo que quieres permitir. Se define un directorio inicial (por ejemplo, $HOME) y una lista de extensiones válidas, como .db.

Tras ejecutar Application.Run($Dialog), se comprueba que el usuario no haya cancelado y que exista una ruta de archivo seleccionada. Si todo es correcto, se actualiza el campo de texto que guarda la ruta (por ejemplo, $txtPath.Text) y se aprovecha para llamar de nuevo a RefreshCategoryList y RefreshTable, de forma que la aplicación pase a trabajar automáticamente con la nueva base de datos elegida.

Para mantener al usuario al día de la hora actual, también es frecuente definir una función UpdateStatusTime que actualiza el título del primer ítem de la barra de estado con la fecha y hora, ejecuta Application.Refresh y devuelve un valor booleano, lo que permite engancharla a un temporizador o mecanismo de refresco periódico.

Confirmaciones y modo WhatIf en TUI

Cuando tu aplicación TUI permite crear, modificar, completar o eliminar tareas, es fundamental incorporar algún tipo de confirmación antes de ejecutar acciones destructivas. Una forma elegante de hacerlo es mediante una función ShowWhatIf, que genere mensajes de tipo “así quedaría el comando” según la acción elegida.

ShowWhatIf suele tomar un parámetro Command con un conjunto de valores predefinidos (New, Set, Complete, Remove) y, en algunos casos, un identificador de tarea. Según el valor recibido, construye un mensaje de texto describiendo el cmdlet que se ejecutaría (New-PSWorkItem, Set-PSWorkItem, Complete-PSWorkItem, Remove-PSWorkItem), junto con la información relevante: nombre, categoría, descripción, progreso, fecha de vencimiento, base de datos, etc.

Para calcular la fecha de vencimiento, la función puede comprobar si el control de días está habilitado. Si lo está, suma el número de días indicado a la fecha actual; si no, toma el valor del campo de fecha explícita. Este mismo patrón se reutiliza tanto en la rama de New como en la de Set, asegurando que el mensaje mostrado coincida con el comportamiento real que tendrá el cmdlet cuando se ejecute en serio.

Una vez montado el bloque de texto (con formato de here-string para mayor claridad), ShowWhatIf lanza Terminal.Gui.MessageBox.Query con un título tipo “WhatIf Operation”, el mensaje y una lista de botones (normalmente solo “Ok”). Así el usuario puede revisar con calma lo que va a ocurrir antes de pulsar el botón que dispara de verdad el comando.

Este patrón se integra a la perfección con la filosofía de PowerShell, donde el parámetro -WhatIf y los mensajes de simulación son muy comunes. LLevar esa misma idea a la TUI refuerza la seguridad y la confianza del usuario cuando opera con datos importantes o potencialmente destructivos.

Combinar Terminal.Gui con PowerShell abre la puerta a desarrollar verdaderas “apps de consola” con menús, cuadros de diálogo y tablas, reutilizando toda la potencia de los cmdlets y de .NET. Con un módulo que gestione los binarios para .NET Core y .NET Framework, una función de conversión a DataTable y unas cuantas rutinas para refrescar formularios, mostrar ayuda y confirmar acciones, es posible construir soluciones muy completas que funcionan tanto en Windows PowerShell como en PowerShell 7 sin apenas cambios de código, y que hacen que tus scripts se sientan como auténticas aplicaciones de escritorio, pero en la terminal.