Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Inspeccione e interactúe con la ejecución de aplicaciones Windows desde la línea de comandos. Los agentes de IA y los desarrolladores usan para las pruebas, la depuración y la automatización de la interfaz de usuario.
Visión general
winapp ui proporciona comandos para inspeccionar e interactuar con las interfaces de usuario de Windows aplicación.
Usa Windows Automatización de la interfaz de usuario (UIA). Funciona con cualquier aplicación de Windows: WPF, WinForms, Win32, Electron y WinUI 3.
La mayoría de los comandos impulsan la aplicación a través de patrones UIA (sin inyección de entrada); ui click es la excepción y usa la simulación real del mouse para los controles que no admiten InvokePattern.
Quick Start
# Connect to any app and see its UI tree
winapp ui inspect -a notepad
# Find specific elements
winapp ui search Button -a notepad
# Activate an element
winapp ui invoke Close -a notepad
# Take a screenshot
winapp ui screenshot -a notepad
Aplicaciones de destino
Por nombre de proceso
winapp ui inspect -a notepad
winapp ui inspect -a slack # auto-picks visible window for multi-process apps
winapp ui inspect -a imageresizer # partial match: finds PowerToys.ImageResizer
Por título de ventana
winapp ui inspect -a "LICENSE - Notepad"
winapp ui inspect -a "Fix WinApp" # partial title match
Por PID
winapp ui inspect -a 12345
Por HWND (estable, sobrevive a los cambios de tabulación o título)
# Discover HWNDs
winapp ui list-windows -a Terminal
→ HWND 985238: "🤖 Testing" (WindowsTerminal, PID 21228)
→ HWND 131906: "Fix WinApp" (WindowsTerminal, PID 21228)
# Target specific window
winapp ui inspect -w 131906
winapp ui screenshot -w 131906
Se usa -a para la detección, -w para destinos estables. Cuando -a coincide con varias ventanas, el comando los enumera con HWND para que elija.
Selectores
Elementos de destino mediante el selector que se muestra en la [brackets] salida de inspección o búsqueda.
Hay tres tipos de selectores:
| Selector | Significado | Example |
|---|---|---|
MinimizeButton |
AutomationId (que se muestra cuando es único, estable, preferido) | winapp ui invoke MinimizeButton -a myapp |
btn-close-d1a0 |
Slug semántico (que se muestra cuando no hay un automationId único) | winapp ui invoke btn-close-d1a0 -a myapp |
Submit |
Búsqueda de texto sin formato en Name/AutomationId (subcadena que no distingue mayúsculas de minúsculas) | winapp ui invoke Submit -a myapp |
Los selectores AutomationId son identificadores del conjunto de desarrolladores (AutomationProperties.AutomationId en XAML).
Cuando un AutomationId es único en todo el árbol inspect de la interfaz de usuario y search lo muestra directamente como selector, estos sobreviven a los cambios de diseño, la localización y la reestructuración del árbol.
Los selectores slug (por ejemplo, btn-close-d1a0) se generan cuando no existe ningún AutomationId único.
Formato: prefix-name-hash. El hash valida la identidad del elemento, pero puede estar obsoleta después de los cambios de la interfaz de usuario.
Inspección del formato de salida
El inspect comando muestra el árbol de elementos con salida coloreado (selector en cian, nombre en verde, metadatos en gris):
TabView Tab (0,-1 1200x48)
TabListView List (4,-1 1100x48)
tab-newtab-5f5b TabItem "New Tab" (14,-1 200x48)
NewTabButton SplitButton "New Tab" [collapsed] (1104,5 96x36)
Found 10 elements (--depth 3). Use the first token as selector, e.g.: winapp ui invoke TabView -a terminal
La primera palabra de cada línea es el selector: úsela con otros ui comandos.
Cuando un elemento tiene un automationId único, se usa directamente (por ejemplo, TabView, NewTabButton).
Cuando no existe ningún automationId único, se usa un slug generado (por ejemplo, tab-newtab-5f5b).
Slugs semánticos
Slugs usa el formato: prefix-normalizedname-hash donde:
- prefijo : abreviatura de tipo de 3 letras (btn, txt, chk, cmb, itm, tab, img, lbl, pn, win, grp, lnk, mnu, etc.)
- normalizedname : alfanumérico en minúsculas de AutomationId (preferido) o Name, max 15 chars
- hash : hash hexadecimal de 4 caracteres del runtimeId del elemento (valida la identidad del elemento)
Los slugs son seguros para shell (sin caracteres especiales), únicos y se pueden usar directamente como argumentos. El hash proporciona detección de obsolescencia, si el elemento se ha reemplazado, obtiene: "Elemento puede haber cambiado. Vuelva a ejecutar la inspección."
Los elementos sin nombre o AutomationId muestran solo el prefijo + hash (por ejemplo, pn-c8a3).
Desambiguación de varias coincidencias
Los slugs de inspect/search la salida son únicos, pero pueden cambiar entre cambios de diseño: úselos en nombres de tipo sin formato o texto cuando haya varias coincidencias. Cuando un selector es ambiguo, la CLI imprime todas las coincidencias con sus slugs para que pueda elegir la derecha y volver a ejecutarla con ese slug.
winapp ui search Button -a myapp # shows: btn-ok-a1b2 "OK", btn-cancel-c3d4 "Cancel"
winapp ui invoke btn-ok-a1b2 -a myapp # invoke using slug (preferred)
winapp ui invoke btn-cancel-c3d4 -a myapp # invoke the other Button by its slug
Búsqueda de texto plano
Use texto sin formato para buscar elementos, sin sintaxis especial necesaria:
winapp ui search Minimize -a notepad # finds elements with "Minimize" in Name or AutomationId
winapp ui search Close -a notepad # case-insensitive substring match
winapp ui invoke Minimize -a notepad # search + invoke in one step (disambiguates if needed)
winapp ui search "Save" -a notepad # find elements containing "Save"
winapp ui search "error" -a myapp # case-insensitive match
Cuando una búsqueda de texto coincide con varios elementos (por ejemplo, SettingsExpander donde Group, Button y Text comparten el mismo nombre), la CLI elige automáticamente el único elemento invocable. Si se invocan varios, se muestran todas las coincidencias con slugs.
Para los resultados de búsqueda no invocables (por ejemplo, un TextBlock dentro de un botón), la búsqueda muestra automáticamente el antecesor invocable más cercano, el elemento primario que puede usar con invoke.
Esto funciona para todos los selectores de búsqueda:
lbl-savechanges-a1b2 "Save changes" (120,40 80x20)
^ invoke via: btn-save-c3d4 "Save"
El selector expuesta se puede usar directamente:
winapp ui invoke btn-save-c3d4 -a myapp # invoke the parent Button
Commands
estado
Conéctese a una aplicación y muestre la información de conexión.
winapp ui status -a notepad
winapp ui status -a notepad --json
Inspeccionar
Vea el árbol de elementos de la interfaz de usuario. La salida muestra los slugs semánticos con sangría de 2 espacios para la jerarquía:
winapp ui inspect -a notepad # full window tree, depth 3
winapp ui inspect -a notepad --depth 5 # deeper tree
winapp ui inspect txt-searchbox-e5f6 -a notepad # subtree rooted at element
winapp ui inspect --ancestors btn-close-d1a2 -a notepad # walk up from element to root
winapp ui inspect -a myapp --interactive # invokable elements only, auto-depth 8
winapp ui inspect -a myapp --hide-disabled # hide disabled elements
winapp ui inspect -a myapp --hide-offscreen # hide offscreen elements
Salida de ejemplo (valor predeterminado):
win-aidevgalleryp-f1a3 "AI Dev Gallery Preview" (94,206 1280x1023)
pn-c8a3 (102,207 1264x1014)
btn-minimize-d1a0 "Minimize" (1222,206 48x48)
btn-maximize-e2b1 "Maximize" (1270,206 48x48)
itm-samples-3f2c "Samples" (102,330 72x62)
Salida de ejemplo ( —--interactive solo elementos invocables, lista plana):
btn-minimize-d1a0 "Minimize" (1222,206 48x48)
btn-maximize-e2b1 "Maximize" (1270,206 48x48)
btn-close-d1a2 "Close" (1318,206 48x48)
itm-home-7b3e "Home" (102,268 72x62)
itm-samples-3f2c "Samples" (102,330 72x62)
itm-models-9a4f "Models" (102,392 72x62)
Los elementos pueden mostrar estos marcadores de estado:
-
[on]/[off]/[indeterminate]: estado de alternancia/casilla -
[collapsed]/[expanded]: estado de expandir o contraer para árboles, cuadros combinados, elementos de menú -
[scroll:v]/[scroll:h]/[scroll:vh]: contenedor desplazable (vertical, horizontal o ambos) -
[offscreen]: el elemento no está visible en la pantalla -
[disabled]: el elemento no está habilitado -
value="..."— contenido de texto actual para elementos editables (cuando es diferente de Name)
search
Buscar elementos que coincidan con un selector. La salida muestra los slugs semánticos:
winapp ui search Button -a notepad # all buttons
winapp ui search Close -a notepad # finds elements with "Close" in name
winapp ui search SearchBox -a notepad # finds elements with "SearchBox" in name or AutomationId
winapp ui search Button --max 10 -a notepad # limit results
Ejemplo de resultado:
btn-minimize-d1a0 "Minimize" (1222,206 48x48)
btn-maximize-e2b1 "Maximize" (1270,206 48x48)
btn-close-d1a2 "Close" (1318,206 48x48)
Los slugs que se muestran en la salida (por ejemplo, btn-minimize-d1a0) se pueden usar directamente con otros comandos:
winapp ui invoke btn-minimize-d1a0 -a notepad
get-property
Lee los valores de propiedad de un elemento. Incluye el estado específico del patrón (ToggleState, Value, IsSelected, etc.).
winapp ui get-property btn-submit-7a90 -a myapp # all properties
winapp ui get-property chk-checkbox-b2c3 -p ToggleState -a myapp # checkbox state
winapp ui get-property txt-textbox-a4b1 -p Value -a myapp # current text value
winapp ui get-property cmb-combobox-d5e6 -p ExpandCollapseState -a myapp # expanded or collapsed
captura de pantalla
Capture una ventana o un elemento como PNG. Cuando existen varias ventanas (por ejemplo, la aplicación y el cuadro de diálogo abierto), se componen en un único PNG con cada ventana cosida.
winapp ui screenshot -a notepad # saves screenshot.png in cwd
winapp ui screenshot -a notepad --output my.png # custom filename
winapp ui screenshot -a notepad --json # returns file path as JSON
winapp ui screenshot -w 131906 # target specific HWND (+ its dialogs)
winapp ui screenshot txt-searchbox-e5f6 -a myapp # crop to element bounds
winapp ui screenshot -a myapp --capture-screen # capture from screen (includes popups/overlays)
Cuando los diálogos o elementos emergentes están abiertos, todas las ventanas se componen en un PNG para que pueda ver el estado completo de la interfaz de usuario en una sola imagen.
Use --capture-screen cuando necesite capturar menús emergentes, listas desplegables, controles flotantes o superposiciones de información sobre herramientas. En --capture-screen el modo (y al reintentar después de detectar un marco en blanco), la ventana de destino se lleva primero al primer plano; las capturas de ventana normales no mueven la ventana.
invoke
Active mediante programación un elemento (haga clic en el botón, active la casilla de alternancia, expanda cuadro combinado).
winapp ui invoke btn-submit-7a90 -a myapp # by slug from inspect
winapp ui invoke btn-submit-a1b2 -a myapp # by slug from inspect/search
winapp ui invoke cmb-sizecombobox-b4c5 -a myapp # expand combo box
Intenta patrones en orden: InvokePattern → TogglePattern → SelectionItemPattern → ExpandCollapsePattern.
click
Haga clic en un elemento en sus coordenadas de pantalla mediante la simulación del mouse. Úselo para los controles que no admiten InvokePattern (por ejemplo, encabezados de columna, elementos de lista).
winapp ui click btn-column1-a3f2 -a myapp # single click by slug
winapp ui click "Column1" -a myapp # single click by text search
winapp ui click btn-column1-a3f2 -a myapp --double # double-click
winapp ui click btn-column1-a3f2 -a myapp --right # right-click
set-value
Establezca un valor en un elemento editable (texto para TextBox/ComboBox, número para Slider).
winapp ui set-value txt-textbox-a4b1 "Hello world" -a notepad
winapp ui set-value sld-volume-b2c3 75 -a myapp
get-value
Lea el valor actual de un elemento. Usa una cadena de reserva inteligente: TextPattern (RichEditBox, Document) → ValuePattern (TextBox, Slider) → SelectionPattern (ComboBox, RadioButton, TabView) → Name (etiquetas).
winapp ui get-value doc-texteditor-53ad -a notepad # read full document text
winapp ui get-value SearchBox -a myapp # read TextBox content
winapp ui get-value CmbTheme -a myapp # read ComboBox selected item
winapp ui get-value sld-volume-b2c3 -a myapp # read Slider value
winapp ui get-value lbl-title-a1b2 -a myapp --json # JSON: { "elementId": "...", "text": "..." }
enfoque
Mueva el foco del teclado a un elemento.
winapp ui focus txt-textbox-a4b1 -a notepad
scroll-into-view
Desplácese por un elemento hasta el área visible.
winapp ui scroll-into-view itm-targetitem-c3d4 -a myapp
wait-for
Espere a que un elemento aparezca, desaparezca o haga que un valor alcance un destino.
winapp ui wait-for Button -a myapp --timeout 5000 # wait for any button
winapp ui wait-for btn-submit-7a90 -a myapp --timeout 5000 # wait for specific element
winapp ui wait-for CounterDisplay -a myapp --value "5" --timeout 5000 # wait for element value (smart fallback)
winapp ui wait-for lbl-status -a myapp --property Name --value "Done" --timeout 5000 # wait for specific property
winapp ui wait-for btn-submit-a1b2 --gone -a myapp --timeout 2000 # wait for element to disappear
winapp ui wait-for lbl-status -a myapp --value "Done" --contains # substring match instead of exact equality
Pergamino
Desplácese por un elemento contenedor. Busque contenedores desplazables con search scroll : busque [scroll:v] marcadores (verticales) o [scroll:h] (horizontales).
# Find which elements are scrollable and in which direction
winapp ui search scroll -a myapp
# pn-scrollview-bfef Pane "scrollView" [scroll:v] (main content, vertical)
# pn-scrollviewer-bfb1 Pane "scrollViewer" [scroll:h] (horizontal list)
# Scroll the main content down
winapp ui scroll pn-scrollview-bfef --direction down -a myapp
# Jump to top/bottom
winapp ui scroll pn-scrollview-bfef --to bottom -a myapp
# If you target an element that's not scrollable, scroll walks up to find the nearest scrollable parent
winapp ui scroll itm-someitem-a1b2 --direction down -a myapp
get-focused
Muestra el elemento que actualmente tiene el foco del teclado.
winapp ui get-focused -a myapp
list-windows
Enumere todas las ventanas visibles para una aplicación, incluidas las ventanas emergentes y los cuadros de diálogo.
winapp ui list-windows -a imageresizer
winapp ui list-windows -a Terminal
winapp ui list-windows # all windows (no filter)
Compatibilidad con marcos
| Marco de referencia | Inspeccionar | search | invoke | set-value | captura de pantalla |
|---|---|---|---|---|---|
| WPF | ✅ Árbol completo | ✅ Todas las propiedades | ✅ Todos los patrones | ✅ | ✅ |
| WinForms | ✅ | ✅ | ✅ | ✅ | ✅ |
| Win32 | ✅ | ✅ | ✅ | ✅ | ✅ |
| WinUI 3 | ✅ | ✅ | ✅ | ✅ | ✅ |
| Electrón | ⚠️ Árbol de Chromium | ⚠️ Limitado | ⚠️ Varía | ⚠️ Varía | ✅ |
| Flutter | ⚠️ Básico | ⚠️ Básico | ❌ Mínimo | ❌ | ✅ |
Solución de problemas
| Error | Causa | Solución |
|---|---|---|
| "No se encontró ninguna aplicación en ejecución" | Error de coincidencia de nombres o no en ejecución de la aplicación | Comprobación del nombre del proceso o uso de PID |
| "Coincidencia de varias ventanas" | Valor ambiguo -a |
Uso -w <HWND> de las opciones enumeradas |
| "tiene varias ventanas" | El proceso tiene varias ventanas | Uso -w <HWND> para establecer como destino uno específico |
| "Selector coincidente con N elementos" | Selector heredado ambiguo | Usar slugs de inspect salida, o anexar [0], [1] a selectores heredados |
| "El elemento puede haber cambiado" | El hash slug no coincide con el elemento actual | Volver a ejecutar inspect o search para obtener slugs frescos |
| "no admite ningún patrón de invocación" | No se puede invocar el elemento | Usar inspect en el elemento para buscar un elemento secundario invocable |
| "No se encontró ninguna ventana UIA" | UIA no puede ver el proceso | Use list-windows para buscar el HWND y, a continuación, -w |
| "La ventana tiene un tamaño cero" | La ventana está minimizada | La aplicación se restaurará automáticamente. |
| Menú emergente o desplegable que no está en la captura de pantalla | PrintWindow no captura superposiciones | Usar --capture-screen marca |
Patrones comunes
Navegación y comprobación
winapp ui invoke btn-settings-a1b2 -a myapp # click a button
winapp ui wait-for pn-settingspage-c3d4 -a myapp # wait for page to load
winapp ui screenshot -a myapp --output settings.png # verify visually
Buscar texto e invocar a su elemento primario
# Search shows invokable ancestor; invoke auto-walks to it
winapp ui invoke 'Save changes' -a myapp
# Or search first to see what matches, then invoke
winapp ui search "Save changes" -a myapp; winapp ui invoke btn-save-c3d4 -a myapp
Desambiguar elementos duplicados
winapp ui search '#Image' -a myapp; winapp ui invoke itm-image-a2b3 -a myapp
Captura de pantalla con superposiciones emergentes
winapp ui set-value txt-searchbox-e5f6 "query" -a myapp; winapp ui screenshot -a myapp --capture-screen
Navegar, esperar y comprobar (cadena única)
winapp ui invoke btn-settings-a1b2 -a myapp; winapp ui wait-for pn-settingspage-c3d4 -a myapp --timeout 3000; winapp ui screenshot -a myapp -o settings.png
Detectar, hacer clic y comprobar
winapp ui inspect -a myapp --interactive; winapp ui invoke btn-submit-7a90 -a myapp; winapp ui screenshot -a myapp
Interacción del cuadro de diálogo archivo
Los cuadros de diálogo de apertura y guardado de archivos son cuadros de diálogo estándar Windows con compatibilidad con UIA:
# Trigger the dialog, find it, type the path, confirm
winapp ui invoke btn-openfilebtn-a2b3 -a myapp
winapp ui list-windows -a myapp # find dialog HWND
winapp ui set-value txt-1148-c4d5 "C:\path\to\file.png" -w <dialog-hwnd>
winapp ui invoke btn-open-e6f7 -w <dialog-hwnd>
Use inspect -w <dialog-hwnd> --interactive para detectar los slugs reales de un cuadro de diálogo específico.
Por qué ; encadenar (no &&)
El operador de && PowerShell puede inmovilizarse cuando una CLI nativa escribe en stderr o usa secuencias de escape ANSI. Use ; en su lugar: ejecuta cada comando incondicionalmente y evita este interbloqueo. Esto también es mejor para los flujos de trabajo del agente: normalmente quiere que se ejecute la captura de pantalla incluso si la invocación tenía una salida distinta de cero.
Patrones de pruebas de CI
Use wait-for con --property y --value actúa como aserción: devuelve el código de salida 1 en el tiempo de espera y produce un error en el paso de CI automáticamente.
Inicio y prueba en Acciones de GitHub
steps:
- name: Build
run: dotnet build MyApp.csproj -c Debug -p:Platform=x64
- name: Launch and test
run: |
$result = winapp run .\bin\x64\Debug\net8.0-windows10.0.26100.0\win-x64 --detach --json | ConvertFrom-Json
$appPid = $result.ProcessId
# Wait for window to initialize
winapp ui wait-for "Main Window" -a $appPid --timeout 30000
# Run tests — each wait-for exits non-zero on failure
winapp ui invoke "Login" -a $appPid
winapp ui wait-for "Dashboard" -a $appPid --timeout 10000
winapp ui screenshot -a $appPid -o dashboard.png
Estado del elemento Assert con wait-for
wait-for --value sondea hasta que el valor de un elemento coincide con la cadena esperada, usando la misma reserva inteligente que get-value (TextPattern → ValuePattern → SelectionPattern → Name). Devuelve el código de salida 0 en coincidencia, el código de salida 1 en el tiempo de espera, lo que lo convierte en una aserción compatible con CI. Use --property para comprobar una propiedad UIA específica en su lugar.
# Assert: button click updated the counter (smart value fallback — works for TextBlock, TextBox, etc.)
winapp ui invoke "Counter Button" -a $pid
winapp ui wait-for "Counter Display" -a $pid --value "Count: 1" -t 5000
# Assert: text input was accepted
winapp ui set-value "Search Box" "hello world" -a $pid
winapp ui wait-for "Search Box" -a $pid --value "hello world" -t 3000
# Assert: checkbox was toggled (use --property for specific UIA properties)
winapp ui invoke "Dark Mode" -a $pid
winapp ui wait-for "Dark Mode" -a $pid --property ToggleState --value "On" -t 3000
# Assert: navigation happened (new page appeared)
winapp ui invoke "Settings" -a $pid
winapp ui wait-for "Settings Page" -a $pid -t 10000
# Assert: dialog was dismissed (element disappeared)
winapp ui invoke "Close" -a $pid
winapp ui wait-for "Dialog Title" -a $pid --gone -t 5000
Aserción con salida JSON
Use --json con PowerShell o jq para aserciones más complejas:
Contrato de código de salida para
searchywait-foren modo: cuando ningún elemento coincide () o el tiempo de espera agotado (), el comando escribe un sobre de resultado totalmente analizable en--jsonstdout ({ "matchCount": 0, ... }o{ "found": false, "timedOut": true, ... }) y devuelve el código de salida 1.wait-forsearchStderr está vacío en--jsonmodo (se suprime la salida del registrador). Bifurcación en los campos de sobre, o en$LASTEXITCODE, dependiendo de cuál sea más ergonómica.
# Assert: search found exactly one match
$result = winapp ui search "Submit" -a $pid --json | ConvertFrom-Json
if ($result.matchCount -ne 1) { throw "Expected 1 Submit button, found $($result.matchCount)" }
# Assert: element has expected properties
# inspect --json returns { windows: [{ hwnd, title, elements: [...] }] };
# each window's elements[] is the nested tree (children rendered via .children).
$tree = winapp ui inspect "Counter Display" -a $pid --json | ConvertFrom-Json
$counter = $tree.windows[0].elements[0]
if ($counter.name -ne "Count: 3") { throw "Counter value wrong: $($counter.name)" }
Ejemplo de prueba de humo completo
# Launch
$app = winapp run .\build-output --detach --json | ConvertFrom-Json
# Verify app loaded
winapp ui wait-for "Main Page" -a $app.ProcessId -t 30000
# Interact and assert
winapp ui invoke "Add Item" -a $app.ProcessId
winapp ui set-value "Item Name" "Test Item" -a $app.ProcessId
winapp ui invoke "Save" -a $app.ProcessId
winapp ui wait-for "Test Item" -a $app.ProcessId -t 5000 # assert item appeared in list
winapp ui wait-for "Save" -a $app.ProcessId --gone -t 3000 # assert save dialog closed
# Visual verification
winapp ui screenshot -a $app.ProcessId -o smoke-test.png