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). Las excepciones insertan entrada real: ui click/ui hover/ui draguse la simulación del mouse,ui touch/ui pen sintetizan la entrada táctil y lápiz/lápiz, y ui send-keys sintetizan la entrada del teclado, para controles y escenarios que los patrones UIA no pueden controlar.
Important
Requisito de escritorio interactivo (verbos de inserción de entrada).click, hover, drag, touchpen, , scroll --wheely send-keys --via send-input sintetizar la entrada de nivel de sistema operativo, por lo que necesitan un escritorio interactivo desbloqueado con la ventana de destino en primer plano. En una estación de trabajo bloqueada o en un escritorio seguro (LogonUI/UAC), no pueden insertar y producir errores rápidos ( no_interactive_desktop distintos de la elevación oforeground_not_target los casos).
touch
/
pen niegue además cuando no se resuelve ninguna ventana (no_target); una coordenada fuera de la ventana de destino es una advertencia no irrecuperable (una warnings[] entrada bajo --jsono una línea de advertencia en modo de texto) y la inyección sigue funcionando, coherente con los verbos del mouse. Todo lo demás , inspect, , get-valueset-valuewait-forget-propertysearch, invokescroll --direction/--to controla la aplicación a través de patrones de UIA y es fácil de usar la sesión bloqueada o sin encabezado.
screenshot es la excepción entre los verbos que no se insertan: toma un turno exclusivo y su captura puede necesitar un escritorio interactivo utilizable, ya que el motor restaura un destino minimizado y vuelve a colocarlo en primer plano cuando la captura de fotogramas no está disponible o --capture-screen se usa. Preferir los verbos de patrón UIA en CI; reserve los verbos de inyección para escenarios que realmente necesitan una entrada real. Antes de insertar, los verbos de gesto también vuelven a resolver el elemento de destino y se niegan con target_moved si todavía se animan o reubican, en lugar de la entrada de aterrizaje en el espacio vacío.
Quick Start
Ejecutar winapp ui --help para el bucle principal: inspect -a <app> --interactive para ver lo que puede actuar invoke o set-value para actuar, y get-value para comprobar el resultado. Cada comando --help muestra ejemplos. Un comando desconocido, como winapp ui dump, se cierra con el código 1 y sugiere los comandos más cercanos (como un error JSON con suggestions cuando se pasa --json).
# 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
Ejecución de la automatización de la interfaz de usuario en Windows espacio aislado
Para mantener la automatización fuera del escritorio, agregue --on sandbox a los comandos de ejecución e interfaz de usuario:
winapp run . --on sandbox --detach
winapp ui inspect --on sandbox -a MyApp
winapp ui invoke --on sandbox SubmitButton -a MyApp
--detach devuelve después del inicio; sin ella, run espera a que se cierre la aplicación. Mantenga todos --on sandbox los comandos de invitado, incluidos los que usan un identificador de PID o una ventana.
Consulte Windows ejecución de espacio aislado para conocer los requisitos del cliente, los breves cambios de foco de configuración y reconexión, la coordinación del flujo de trabajo y la entrega de salida del host.
Consultas con ámbito y tipadas
winapp ui search "Welcome to MyApp" -a myapp --root MailRow --type Text --class-name TextBlock
winapp ui get-value Subject -w 123456 --root MailRow --type TextBox
winapp ui get-property Subject -a myapp --root MailRow --type Edit --property Value
winapp ui wait-for Subject -a myapp --root MailRow --type Edit --value "Ready" --timeout 10000
winapp ui invoke Open -w <dialog-HWND> --type Button
winapp ui set-value "Text editor" "hello" -a notepad --type Document
Estos comandos aceptan filtros opcionales en su selector de elementos: inspect (con un selector), search, get-property, wait-forfocusget-valueclickinvokeset-value, scrollhoverscreenshotrecordscroll-into-view, , touchy .pen
drag (dos selectores) y send-keys --target no.
El selector y todos los filtros proporcionados deben coincidir con el mismo elemento. Los filtros limitan un selector, por lo que inspect, screenshoty record, cuyo selector es opcional, producen invalid_arguments un error cuando se proporcionan filtros sin uno. Para touch y pen, los filtros necesitan un selector; no se pueden combinar con --at o --path (invalid_arguments):
-
--root <selector>solo busca descendientes de una raíz que coincida de forma única, nunca la propia raíz. Use automationId o slug deinspectpara desambiguar. Se produce un error en una raíz que coincide con varios elementos conambiguous_selector, incluso si se invoca una coincidencia. Una raíz que falta no produce coincidencias. Una vez que se encuentra la raíz, las consultas no buscan ventanas emergentes no relacionadas, incluso cuando no hay coincidencias descendientes. Las consultas no están limitadas porinspectla profundidad de visualización. -
--type <control-type>coincide con un tipo de control UIA, ignorando mayúsculas y minúsculas. Los únicos alias sonTextBox→EdityTextBlock→Text. Los nombres desconocidos (incluidos los identificadores numéricos y las expresiones con caracteres comodín) producen un error coninvalid_arguments. -
--class-name <literal>coincide con la UIAClassNamecompleta del proveedor, ignorando el caso. No es una subcadena, un carácter comodín ni una expresión regular. Useget-property --property ClassNamepara detectar el valor del proveedor; el nombre de clase no necesita igual al tipo de control UIA.
Las consultas filtradas usan la vista de control de UIA, la misma vista que muestra inspect.
Los nodos de proveedor expuestos solo en la vista sin formato no se devuelven; use inspect para buscar el control contenedor y su selector.
Se admiten los 41 tipos oficiales: Button, Calendar, CheckBoxImageDataItemListItemDocumentListSplitButtonMenuAppBarProgressBarSemanticZoomMenuItemSeparatorRadioButtonTitleBarMenuBarTableScrollBarHyperlinkGroupSliderThumbSpinnerDataGridHeaderCustomHeaderItemPaneWindowTreeItemTreeToolTipToolBarTabItemStatusBarTextComboBoxEditTab.
wait-for resuelve de nuevo el selector raíz en cada sondeo, por lo que la raíz puede aparecer después de que se inicie el comando. Con --gone, una raíz ausente significa que no hay ningún descendiente coincidente; una raíz ambigua es un error, no correcto.
Una búsqueda interrumpida no es prueba de desaparición: si se quita un elemento durante la búsqueda o se reemplaza antes de una --value lectura, el siguiente sondeo vuelve a comprobar; otros errores de búsqueda o lectura producen un error en el comando.
-w <HWND> restringe la detección raíz al árbol UIA de esa ventana. Con -a, la detección raíz también puede encontrar las ventanas emergentes de la aplicación. Las coincidencias de AutomationId raíz exactas tienen prioridad sobre las coincidencias de subcadena en todas esas ventanas; todavía se produce un error en varias coincidencias exactas con ambiguous_selector.
Un slug raíz selecciona ese elemento incluso cuando otra ventana tiene el mismo AutomationId. Si se reemplaza la raíz seleccionada, su antiguo slug ya no coincide; use un automationId o una raíz de nombre cuando desee que el sondeo siga un reemplazo.
Cuando los filtros están presentes, cada comando excepto search se produce un error si ambiguous_selector permanece más de un elemento; restrinja los filtros o use un slug único. Los comandos que actúan en el recuento de elementos coinciden en cada ventana que buscan, por lo que un control coincidente en un cuadro de diálogo de propiedad también hace que el selector sea ambiguo. Las coincidencias de AutomationId exactos conservan la prioridad sobre las coincidencias de subcadena, dentro del ámbito filtrado. Si se omiten las tres opciones, se conserva el comportamiento de la consulta existente.
Coordinación de flujos de trabajo simultáneos de la interfaz de usuario
Windows solo tiene una ventana de primer plano, un foco de teclado, un cursor y una secuencia de entrada. Cuando dos winapp ui flujos de trabajo se ejecutan en el mismo escritorio con sesión iniciada a la vez, pueden robar el foco entre sí, descartar un menú que acaba de abrir o mover un destino desde un clic pendiente.
El arbitraje siempre está activado. Cada winapp ui comando que toca el escritorio físico toma un turno, sin configuración y sin forma de desactivarlo, por lo que dos agentes nunca pueden escribir en las ventanas de los demás. Los comandos de solo lectura siguen ejecutándose simultáneamente. La única excepción es un proceso que no puede tener acceso a la carpeta de coordinación de winapp, como un espacio aislado del agente que bloquea %USERPROFILE%\.winapp: sus comandos siguen ejecutándose, pero sin realizar turnos, e impriman una advertencia (excepto con --json o --quiet).
La continuidad entre los comandos es opcional. De forma predeterminada, cada comando es una toma única independiente: espera su turno, realiza su trabajo y libera el escritorio inmediatamente. Para mantener el escritorio en varios comandos, asígneles el mismo identificador de flujo de trabajo:
# Set once per logical UI workflow
$env:WINAPP_UI_WORKFLOW_ID = [guid]::NewGuid().ToString()
Cosas que necesitas saber:
- Un identificador de flujo de trabajo denomina un flujo de trabajo lógico , no necesariamente un agente completo y no necesariamente una aplicación. Use el mismo valor para los comandos de cooperación (una grabación más los clics que debe capturar); use valores diferentes para flujos de trabajo independientes, incluso cuando un agente inicia ambos.
- Sin identificador, cada comando es una toma única independiente. Todavía arbitra, pero no tiene gracia y entrega el escritorio fuera del momento en que termina. Dos comandos no-id son flujos de trabajo independientes incluso cuando se inician desde el mismo shell.
- Los hosts adaptables y de shell nuevo deben insertar el mismo valor. Si cada comando se ejecuta en un nuevo shell , que es la forma en que la mayoría de las llamadas a la herramienta del agente funcionan, lo único que puede agruparlos es un pase explícito
WINAPP_UI_WORKFLOW_IDa cada llamada de cooperación. - La gracia de cuatro segundos protege las ráfagas estrechas, no el razonamiento del modelo. Un flujo de trabajo con un identificador mantiene su turno siempre que el siguiente comando se inicie en cuatro segundos. Esto cubre los comandos de retroceso en un script; expira intencionadamente mientras un modelo está pensando. Es una reserva para cuando no se puede decir que ha terminado, cuando se puede, ejecutar
winapp ui yielden lugar de esperarlo. - Los flujos de trabajo adaptables deben volver a adquirir, volver a validar y reproducir. Después de un hueco de razonamiento, otro flujo de trabajo puede haber usado el escritorio, así que vuelva a abrir el menú, vuelva a resolver el elemento y, a continuación, actúe. Envíe secuencias de un extremo a otro conocidas como un script ajustado en lugar de mantener el escritorio mientras piensa.
- La ordenación es primero la afinidad de propietario y, después, FIFO entre los demás. Aunque un flujo de trabajo está activo o dentro de su gracia, puede seguir emitiendo comandos, incluso si otros flujos de trabajo ya están esperando. Una vez que se ejecuta
winapp ui yieldo su gracia expira, los flujos de trabajo en espera se sirven en orden de llegada estricto. La actividad continua por un flujo de trabajo puede retrasar a otros de forma indefinida. - No hay capucha dura. Un script largo, una grabación sin enlazar o un bucle de error puede bloquear otros flujos de trabajo de mutación.
-
La cancelación o la terminación del proceso es la recuperación de un flujo de trabajo activo bloqueado. Los comandos en espera imprimen un estado después de un segundo y se pueden detener con
Ctrl+C, que sale130de . - Solo cooperan los archivos binarios actualizados compatibles. Las compilaciones anteriores
winapppredescriben esta característica y no están coordinadas. El código que llama directamente a los paquetes NuGet de Automatización de la interfaz de usuario está fuera de esta garantía por completo: la coordinación reside en la CLI, no en los paquetes.
Qué comandos esperan un turno:
| Behavior | Commands |
|---|---|
| Se ejecuta simultáneamente (nunca espera) |
status, list-windows, inspect, search, get-property, get-value, get-focused, wait-for |
| Espera el turno, pero nunca toma el escritorio |
set-value, scroll-into-view, ,/scroll --direction--to ,record |
| Espera el turno y toma el escritorio exclusivamente |
invoke, click, drag, hover, scroll --wheel, touch, pen, focus, send-keys, screenshot |
La fila central es la que merece la pena comprender.
set-value
--to
scroll --direction
/y scroll-into-view impulsan patrones UIA en lugar del primer plano, por lo que permanecen atentos a la sesión bloqueada o sin encabezado y nunca impiden que nadie use el escritorio. Pero cambian lo que muestra la aplicación, por lo que esperan detrás del turno de otro flujo de trabajo en lugar de editar un campo o desplazarse por una lista desde el clic de otro usuario.
Dentro de un flujo de trabajo se superponen con otro trabajo compartido , es decir, cómo captura record las set-value llamadas que está grabando.
No omiten la barrera hacia delante de su propio flujo de trabajo: un comando anterior DesktopExclusive del mismo flujo de trabajo (un click, a screenshot) todavía los bloquea, exactamente igual que bloquea cada comando posterior, por lo que un clic y la mutación que sigue se mantiene en el orden en que los escribió.
screenshot siempre pone en cola un turno exclusivo. No todas las capturas alteran el escritorio ( una ventana visible normal capturada a través de Windows Captura de gráficos no), pero el motor restaura el destino si está minimizado y vuelve a primer plano cuando la captura de fotogramas no está disponible o --capture-screen lee la pantalla en directo. Estas solo necesitan superficie una vez que la captura está en curso, por lo que el comando toma el turno delante en lugar de adivinar. Cuando compone varias ventanas, las captura todo debajo de un turno exclusivo, por lo que la imagen guardada es un solo momento coherente en lugar de una combinación de antes y después. La codificación y escritura del archivo se produce después de que se libere el escritorio.
--capture-screennecesita exactamente una ventana. La captura en pantalla activa registra lo que realmente está delante y solo puede haber una ventana. Seleccionar una ventana explícitamente con-w <hwnd>proporciona exactamente una región: los píxeles dentro de los límites de esa ventana, incluido cualquier cuadro de diálogo o superposición visiblemente encima de ella, que es la razón para leer la pantalla en primer lugar. Cuando-acoincide con varias ventanas de nivel superior o de propiedad no hay ninguna selección de este tipo, por lo que el comando produce un errorinvalid_argumentsantes de capturar nada en lugar de luchar contra el primer plano. Ejecutewinapp ui list-windows -a <app>y vuelva a intentarlo con-w <hwnd>o suelte--capture-screencada ventana desde su propio contenido.
record comparte su turno, por lo que la entrada del mismo flujo de trabajo puede intercalar con la captura, es decir, cómo registra un flujo de trabajo que conduce una aplicación. Dos advertencias:
- Un
recordsin identificador de flujo de trabajo es un propietario único, por lo que bloquea todos los demás flujos de trabajo durante toda su duración. Para registrar y hacer clic al mismo tiempo, asigne a ambos comandos el mismoWINAPP_UI_WORKFLOW_ID. - En un host sin compatibilidad con captura de fotogramas, la grabación vuelve a PrintWindow, cuya recuperación de fotogramas en blanco puede en primer plano la ventana en cualquier momento. Allí se mantiene el escritorio para toda la grabación y el comando lo dice en su salida; Incluso la entrada del mismo flujo de trabajo esperará.
Errores que puede ver: invalid_ui_workflow_id (la variable se establece pero está vacía o más de 256 caracteres), desktop_coordination_unavailable (el estado de coordinación es ilegible y no se puede volver a generar de forma segura o se ha escrito con una versión más reciente winapp), queue_capacity_exceeded (64 comandos de otros flujos de trabajo ya están esperando: el límite cuenta los waiters extranjeros activos, no los procesos que se han iniciado, por lo que las entradas que pertenecen a comandos que han salido o eliminado no ocupan una ranura, y los comandos de su propio flujo de trabajo se ponen detrás de otros en lugar de en este límite), ui_turn_busy (yield mientras que su propio flujo de trabajo sigue teniendo un comando en ejecución) y cancelled (Ctrl+C mientras espera, salir del código 130).
Liberando el turno temprano: winapp ui yield
La gracia de cuatro segundos es una reserva: mantiene el escritorio reservado cuando no se puede decir para asegurarse de que ha terminado. Cuando puedas decirlo, dilo, yield entrega el escritorio inmediatamente en lugar de hacer que todos los demás esperen una gracia que nadie necesite.
$env:WINAPP_UI_WORKFLOW_ID = [guid]::NewGuid().ToString()
winapp ui invoke File -a notepad
winapp ui click "Save As..." -a notepad
winapp ui set-value txt-filename-a1b2 "notes.txt" -a notepad
winapp ui yield # done — a waiting workflow starts now, not in four seconds
- Los comandos de captura única no deben establecer un identificador de flujo de trabajo en absoluto. Sin uno, cada comando ya libera el escritorio el momento en que finaliza y no hay nada que producir.
- Los flujos de trabajo de varios pasos deben producir cuando finalizan, especialmente cuando otros flujos de trabajo pueden estar esperando. Cuesta un comando rápido y quita un puesto de cuatro segundos de todos los demás.
- Es idempotente. Si se produce dos veces o después de que la gracia ya ha expirado, se realiza correctamente e informa
{ "released": false }, es decir, el final normal de un script, no un error. - Nunca libera el turno de otro flujo de trabajo. Si alguien más mantiene el escritorio, o nadie lo hace, es un no-op.
- Se produce un error si
ui_turn_busysu propio flujo de trabajo todavía tiene un comando en ejecución o en cola, por ejemplo, una grabación. Liberar debajo de eso dejaría el escritorio fuera del comando medio, por lo que no se libera nada y el comando en ejecución no se ve afectado. Espere o deténgalo y vuelva a producirlo. - Requiere
WINAPP_UI_WORKFLOW_ID. Sin uno, se produce un error coninvalid_arguments. - No toma ninguna aplicación y ningún selector: devuelve una reserva, no una ventana, por lo que sigue funcionando después de que la aplicación se haya cerrado.
El usuario que libere el escritorio en lugar de sondear un comando en espera se reactiva, por lo que una cola no cuesta casi nada mientras espera y entrega es inmediata. Cada waiter también vuelve a comprobar por sí mismo ocasionalmente, que es lo que recupera el escritorio cuando se mata un proceso y nunca publica nada: el comando en el encabezado de la cola se ve cada medio segundo y los comandos detrás de él, que no se pueden ejecutar antes de que la cabeza haga de todos modos, cada pocos segundos.
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
winapp ui search Seven -a calculator # hosted app: uses the frame window that hosts it
Algunas aplicaciones empaquetadas (por ejemplo Calculadora) no tienen ninguna ventana propia; otro proceso hospeda su marco. Cuando el proceso coincidente (por nombre o PID) no tiene ninguna ventana visible, -a usa el marco que hospeda su contenido en su lugar. Si no hay ninguna (por ejemplo, la aplicación sigue iniciando), -a tiene como destino el proceso, por lo que wait-for sigue buscando hasta que aparezca su ventana.
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. Sin filtros de consulta, el hash proporciona detección de obsolescencia; si el elemento se ha reemplazado, obtiene: "El elemento puede haber cambiado. Vuelva a ejecutar la inspección." Para las consultas filtradas, consulte Consultas con ámbito y tipadas.
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 # elements you can invoke, click, or set-value; 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 accionables, 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
winapp ui get-property Document -p FontWeight -a myapp --json # document formatting
Los nombres de propiedad distinguen mayúsculas de minúsculas. Se produce un error en un nombre desconocido con invalid_arguments--json; se omite para enumerar --property las propiedades, incluidos los seis atributos de formato de texto siguientes.
wait-for --property usa los mismos nombres que distinguen mayúsculas de minúsculas y rechaza nombres desconocidos antes del sondeo.
Formato de texto de documento completo
El formato se lee en todo el documento TextPattern del elemento, no en su selección o intercalación actual. Las lecturas no cambian el foco ni la selección.
| Property | Valor uniforme (devuelto como una cadena) |
|---|---|
FontWeight |
Peso numérico, como "400" (normal) o "700" (negrita) |
FontName |
Nombre de familia de fuentes, como "Courier New" |
FontSize |
Tamaño en puntos, como "15.5" |
ForegroundColor |
Decimal Windows COLORREF (0x00BBGGRR), como "3678732" para RGB(12, 34, 56) |
IsItalic |
"True" o "False" |
StrikethroughStyle |
Estilo de decoración de texto UIA numérico, como "0" (ninguno) o "1" (único) |
Los números usan formato invariable (un separador decimal, independientemente de la configuración regional). En su lugar, cada atributo puede devolver:
| Value | Significado y paso siguiente |
|---|---|
"Mixed" |
El formato varía dentro del documento. No lo trate como un valor uniforme; este comando no consulta intervalos de texto individuales. |
"NotSupported" |
El proveedor TextPattern del documento no notifica este atributo. Compruebe la compatibilidad con la accesibilidad de la aplicación. |
"Unavailable" |
El elemento no tiene TextPattern. Use inspect o search para buscar su elemento text/document. |
Al enumerar todas las propiedades, las propiedades básicas almacenadas en caché permanecen disponibles si no se puede resolver ningún elemento activo y se omite un valor de formato incorrecto sin descartar otras propiedades. Estas omisiones se registran como advertencias. Solicite una propiedad de formato específica para obtener un error en lugar de una omisión.
Los errores del proveedor siguen siendo errores, no "Unavailable". Para stale_element, vuelva a inspeccionar la aplicación y vuelva a intentarlo con un selector actual.
El sobre JSON incluye elementId, un tipo elementy con propertiesvalores de cadena.
Las propiedades existentes, incluidas BoundingRectangle, conservan sus formatos.
Por ejemplo, la parte de formato de properties es:
{
"FontWeight": "700"
}
captura de pantalla
Capture una ventana o un elemento como PNG.
winapp ui screenshot -a notepad # saves screenshot.png in cwd
winapp ui screenshot -a notepad --output my.png # custom filename
winapp ui screenshot --quiet -a notepad -o my.png # save without informational output
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 -w 131906 --capture-screen # one screen region, with visible overlays in place; foregrounds window
winapp ui screenshot -a myapp --focus # bring window to foreground first, then capture (default WGC path)
Sin un selector de elementos, la captura predeterminada combina varias ventanas en una etiqueta PNG compuesta en paralelo, no en archivos independientes.
-a por nombre de proceso o PID incluye las ventanas de la aplicación y sus ventanas propiedad. Una coincidencia basada en -a título selecciona una ventana coincidente más sus ventanas de propiedad; -w selecciona explícitamente una ventana más sus ventanas propiedad, no todas las ventanas del proceso. Por lo tanto, un cuadro de diálogo o información sobre herramientas propiedad puede aparecer como su propio panel incluso cuando se selecciona explícitamente el HWND principal. Un selector de elementos recorta ese elemento en lugar de componer ventanas. Un elemento de un menú, control flotante, información sobre herramientas o sugerencia de enseñanza que se abre en su propia ventana emergente se recorta desde ese elemento emergente, no desde la ventana detrás de ella.
--quiet suprime la salida informativa de las capturas compuestas y de una sola ventana, incluida la ruta de acceso guardada. Las advertencias y los diagnósticos de errores de captura permanecen visibles. Use --json en su lugar cuando necesite la ruta de acceso del archivo y las dimensiones como salida estructurada.
Con --on sandbox, --output asigna un nombre al destino del host. Salida sin formato correcta e --json informe de esa ruta de acceso de host después de que se entregue la imagen.
La ruta de acceso de captura predeterminada usa Windows. Graphics.Capture (WGC), leyendo la superficie compuesta por DWM real, conservando las esquinas redondeadas, la transparencia y trabajando incluso mientras otras windows ocluyen la ventana. Si WGC no está disponible (compilaciones anteriores Windows), la CLI vuelve a PrintWindow.
Use --capture-screen -w <hwnd> cuando necesite elementos emergentes o información sobre herramientas visibles en sus posiciones en pantalla, incluidas las superposiciones que no pertenecen a la ventana de destino. Lee la región de pantalla de esa ventana en lugar de componer paneles etiquetados y lleva primero la ventana al primer plano. Con -a, requiere exactamente una ventana coincidente; si coinciden varias ventanas de nivel superior o de propiedad, use winapp ui list-windows -a <app> y vuelva a intentarlo con -w <hwnd>. Use --focus si solo desea poner en primer plano la ventana sin cambiar los modos de captura (por ejemplo, para asegurarse de que la captura de pantalla coincide con lo que el usuario está viendo actualmente).
Dado que el controlador de dominio de pantalla captura lo que realmente está delante,
--capture-screencomprueba que el destino alcanzó el primer plano inmediatamente antes de capturar y produce un error siforeground_not_targetno lo hacía (prevención de robo de foco, un aviso de UAC u otra ventana que se activa a sí mismo). No se escribe ninguna imagen en ese caso, anteriormente el comando salió 0 y devolvió una imagen de la ventana incorrecta.ui record --capture-screenaplica la misma comprobación antes del primer fotograma.
registro
Registre una ventana o región de elemento en un MP4 H.264. Se prefiere un positivo --duration-sec para los scripts desatendidos. Sin una duración, la grabación continúa hasta Ctrl+C o, para stdin redirigido, una nueva línea o EOF. Los asistentes y targetRecord npm uiRecord requieren un entero durationSec de 1 a 86400; su señal de anulación se cancela de forma forzada en lugar de finalizar correctamente una grabación.
# Record for 10 seconds
winapp ui record -a myapp --duration-sec 10 --fps 15 --output demo.mp4
# Add agent-readable frames
winapp ui record -a myapp --frames --duration-sec 10 --fps 10 --output evidence.mp4 --json
# Stop an unbounded recording through stdin
"" | winapp ui record -a myapp --json --output capture.mp4
# Include screen overlays and popups
winapp ui record -a myapp --capture-screen --duration-sec 5 --output with-popups.mp4
Opciones:
-
--duration-sec N: registro durante N segundos. 0 registros predeterminados hasta que se detengan. -
--fps N: fotogramas de destino por segundo (valor predeterminado 15). -
--max-edge N— Escala inferior para que el borde más largo sea como máximo N píxeles (0 = sin escala inferior). -
--capture-screen— Captura desde el controlador de dominio de la pantalla (incluye superposiciones o elementos emergentes; en primer plano la ventana). -
--output <path>: ruta de acceso MP4 de salida. Tiene como valor predeterminadorecording-<timestamp>-<guid>.mp4. -
--overwrite: reemplace las salidas de grabación existentes después de que finalice la nueva toma. Sin ella, se rechazan las salidas existentes. -
--frames— Escriba evidencia JPEG con marca de tiempo en<output-name>.frames. Admite 1-30 fps y--max-edge64-4096 (valor predeterminado 1280). Los datos de fotogramas están limitados a 1 GiB; el MP4 continúa si se alcanza el límite.
Artefactos de marco legibles por agente:
evidence.mp4
evidence.frames/
manifest.json
frames.ndjson
frames/
frame-000000-t000000000012.jpg
frames.ndjson tiene una línea por ejemplo con sampleIndex, monotonica elapsedMs, MP4 relativa mediaTimeMsa , imageIndex, filey changed. Las muestras idénticas a píxeles consecutivas reutilizan la calidad-85 JPEG anterior.
manifest.json registra la solicitud, el tiempo, el estado mp4, las dimensiones de imagen y el estado (complete, partialo truncated). El tiempo truncado cubre el prefijo retenido, mientras video que describe el MP4 completo.
Elija una nueva ruta de acceso de salida a menos que quiera reemplazar una grabación por --overwrite.
Sin él, ya sea un vídeo existente o su directorio emparejado .frames bloquea la grabación, incluso cuando se omite --frames.
El MP4 anterior permanece intacto si se produce un error en la nueva captura. Si el reemplazo se realiza correctamente, el directorio de fotogramas anterior se conserva como <output-name>.frames.previous-<id>, incluso si la nueva grabación omite --frames. Conserve la evidencia parcial y siga el informe recoveryHint antes de volver a intentarlo. Si se produce un error en la finalización de MP4, los fotogramas conservados se pueden publicar en <output-name>.frames.partial-*. Los artefactos de marco contienen contenido de pantalla sin cifrar; controlarlos como capturas de pantalla o vídeo.
Con --on sandbox, tanto el MP4 como el directorio frame se entregan al host, incluidas las salidas predeterminadas cuando --output se omite. Consulte Captura de espacio aislado para grabaciones interrumpidas y captura de escritorio completo.
Modos de captura (notificados en el campo JSON mode ):
-
wgc: Windows captura de gráficos (valor predeterminado; funciona mientras la ventana está ocluida). -
printwindow— Impresión de GDIWindow (reserva cuando WGC no está disponible en este sistema o sesión; vuelva a ejecutar con--capture-screenpara usar el controlador de dominio de pantalla en su lugar). -
screen— Dc de pantalla a través--capture-screende (incluye superposiciones o elementos emergentes; lleva la ventana al primer plano).
Salida JSON (--json):
-
stdout: Resultado final de la grabación, incluida la cadencia, el motivo de detención, las advertencias opcionales
frameArtifactsy . -
stderr: Un objeto JSON por línea: un
recording-startedevento después del primer fotograma, seguido de un error si se produce un error en la grabación posterior. Las rutas de acceso de fotograma solo se incluyen cuando la salida del marco está activa.
Códigos de error:
-
element_not_found— El selector no coincide. -
ambiguous_selector— El selector coincide con varios elementos; use un slug sugerido. -
invalid_arguments: un valor de opción no es válido. -
output_exists— Ya existe una salida de grabación y no se puede reemplazar en las opciones solicitadas. -
frame_output_failed: no se puede conservar ninguno de los artefactos después de que se produzca un error en la salida del marco. -
partial_output— Solo se completó un artefacto; inspeccionepartialOutputyrecoveryHint.
Un selector de elementos registra la región del elemento desde la ventana en la que se dibuja. Para un elemento de un menú, control flotante, información sobre herramientas o sugerencia de enseñanza que se abre en su propia ventana emergente, la grabación muestra el elemento emergente en lugar de la ventana detrás de él.
invoke
winapp ui invoke SettingsCategory -a myapp --action select
winapp ui invoke AgreeCheckbox -a myapp --action toggle-on --json
winapp ui invoke SizeComboBox -a myapp --action expand
winapp ui invoke Open -w <dialog-HWND> --root Actions --type Button --class-name Button --action invoke
winapp ui invoke SubmitButton -a myapp
Use --action cuando una prueba debe realizar una operación específica en exactamente el elemento seleccionado. Nunca intenta otro patrón o un antecesor invocable, incluso si se produce un error en la acción solicitada. Se seleccionará un control que admita la invocación y la selección, no invocados, con --action select. Con --action, un slug tiene como destino exactamente un elemento; un selector automationId o texto sin formato que coincide con más de un elemento produce un error cerrado con un código de salida distinto de cero en lugar de actuar en la primera coincidencia, por lo que se pasa un slug de inspect/search cuando un nombre es ambiguo.
--root, --typey --class-name restrinja la coincidencia tal como se describe en Consultas con ámbito y tipadas, con o sin --action.
Use -w <dialog-HWND> para restringir una acción a ese cuadro de diálogo o -a <app> para incluir las ventanas de la aplicación. Una invocación filtrada confirma el destino único antes de actuar, requiere exactamente un elemento coincidente y nunca cambia a otra ventana o a un antecesor invocable. Se produce un error en cero coincidencias con element_not_found; los duplicados producen un error con ambiguous_selector. Se produce un error en un elemento obsoleto o una ventana reciclada sin actuar; vuelva a ejecutar inspect o search elija un selector actual.
Sin --action, una invocación filtrada sigue intentando los patrones en orden en ese elemento.
| Action | Operación |
|---|---|
invoke |
InvokePattern.Invoke |
select |
SelectionItemPattern.Select |
toggle |
TogglePattern.Toggle, exactamente una vez |
toggle-on / toggle-off |
Leer ToggleState; correcto sin cambiar un estado ya correcto; de lo contrario, alternar y comprobar |
expand / collapse |
ExpandCollapsePattern.Expand / Collapse |
Para toggle-on y toggle-off, un estado inicial Indeterminate permite como máximo dos transiciones, comprobando el estado después de cada uno. Otros estados iniciales permiten una transición. Si no se alcanza el estado solicitado, se produce un error en el comando en lugar de continuar con el botón de alternancia. Una comprobación con error puede dejar el control cambiado; lea ToggleState antes de decidir qué hacer a continuación.
Sin --action filtros y sin filtros, el comportamiento automático no cambia: pruebe InvokePattern, TogglePattern, SelectionItemPattern y, a continuación, ExpandCollapsePattern (expand), con un reintento antecesor invocable cuando sea necesario.
Se produce un error en una acción no admitida con un código de salida distinto de cero y, con --json, un error estructurado en stderr. Inspeccione el control seleccionado y elija una acción que admita o establezca explícitamente como destino el elemento primario deseado. Json correcto incluye requestedAction y performedAction; consulte la referencia JSON.
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
Al igual que los otros verbos de inserción de entrada,
clicklleva el destino al primer plano y produce un error rápido (no_interactive_desktopen un escritorio bloqueado o seguro,foreground_not_targetsi el foco no se pudo transferir) en lugar de hacer clic en la ventana incorrecta. También vuelve a resolver el elemento justo antes del botón hacia abajo: después de colocar el cursor, realiza una comprobación de posición final, por lo que se produce un error en un destino de movimiento y animación continuos entarget_movedlugar de notificar el éxito después de que el clic se haya colocado en un espacio vacío, un éxito notificado significa que el destino todavía estaba en su lugar cuando el botón cayó.
Resistencia
Presione el botón del mouse en un punto, muévalo a otro y, a continuación, suelte con drag <from> <to>, donde cada punto de conexión es un selector de elementos (arrastra desde o hacia el centro del elemento) o coordenadas x,yde pantalla exactamente según lo indicado por .winapp ui inspect Mezclar y coincidir libremente (selector→selector, selector→coords, coords→coords).
Usa SendInput con movimientos intermedios para que la aplicación vea una secuencia realista de WM_MOUSEMOVE mensajes. Úselo para reordenar o cambiar el tamaño de los controladores, los controles deslizantes, el dibujo del lienzo y arrastrar y colocar.
winapp ui drag itm-card-9f8e itm-slot-2c1a -a myapp # reorder: card center → slot center
winapp ui drag itm-card-9f8e 300,400 -a myapp # element center → screen coords (from inspect)
winapp ui drag 120,200 480,200 -a myapp # raw screen coords → screen coords
winapp ui drag itm-card-9f8e itm-trash-0001 -a myapp --right # right-button drag
# Press-and-hold / long-press and drop-target dwell
winapp ui drag tile-photo-7b3c tile-photo-7b3c -a myapp --hold-ms 600 # long-press: from == to, hold 600ms, no move
winapp ui drag itm-card-9f8e pane-left-2c1a -a myapp --dwell-ms 350 # settle on the drop target before releasing
Opciones:
-
--right— Arrastre con el botón derecho del mouse en lugar del botón izquierdo. -
--hold-ms <ms>— Mantenga presionado el botón al principio antes de moverse (valor predeterminado: 0). Con<from> == <to>(sin movimiento), esto realiza un gesto de presión y suspensión / presión larga . -
--dwell-ms <ms>— Mora en el destino después de mover, antes de liberar (valor predeterminado: 0). Permite quitar los destinos o combinar superposiciones que el brazo de un puntero sostenido (en lugar del instante que llega el cursor) se cierre temporal antes del botón hacia arriba.
Bare
x,yson coordenadas de pantalla en el mismo informe de espaciowinapp ui inspect/searchy un selector se resuelve en el centro del elemento: inspeccione primero para seleccionar puntos.
Al igual que
send-keys --via send-input,draginserta el sistema operativo en coordenadas de pantalla después de llevar el destino al primer plano. Si el foco no se puede traer al destino (por ejemplo, la prevención de robo de foco de un proceso en segundo plano), se produce un error en el comando (foreground_not_target) en lugar de arrastrar en la ventana incorrecta: el foco o haga clic en la ventana en primer lugar. En un escritorio bloqueado o seguro, se produce un error conno_interactive_desktop. Cada punto de conexión de elemento se vuelve a resolver inmediatamente antes de la arrastrar; si sigue moviendo o cambiando el tamaño (un destino de animación), se produce un error en el comando contarget_moveden lugar de arrastrar a un punto obsoleto. (Los puntos de conexión sinx,ysistema operativo no se pueden volver a comprobar, por lo que se usan as-is).
Toque
Inserte gestos táctiles sintéticos mediante la API de inyección de puntero Windows. El delimitador de contactos es un selector de elementos (usa el centro del elemento) o una coordenada x,yde pantalla explícita a través --at de (informes de mismo espaciowinapp ui inspect). Úselo para las interacciones de pulsar o presionar y gestos multitáctil que la simulación del mouse no puede expresar.
winapp ui touch btn-ok-1a2b -a myapp # tap at the element center
winapp ui touch -a myapp --at 320,240 # tap at explicit screen coords
winapp ui touch tile-photo-7b3c -a myapp --gesture long-press --hold-ms 600
winapp ui touch -a myapp --at 100,300 --gesture swipe --to-point 400,300
winapp ui touch img-map-9f8e -a myapp --gesture pinch --distance 200 # pinch-to-zoom out (2 fingers)
winapp ui touch img-map-9f8e -a myapp --gesture stretch --distance 200 # stretch-to-zoom in (2 fingers)
Opciones:
-
--gesture <g>—tap(valor predeterminado),double-tap,long-press,swipe,pinch, .stretch -
--at <x,y>— Punto de inicio explícito (coordenadas de pantalla). El valor predeterminado es el centro de elementos del selector. -
--to-point <x,y>— Punto de conexión de unswipeobjeto . Tiene prioridad sobre--direction. -
--direction <right|left|up|down>— Dirección del deslizar el dedo (valor predeterminado:right). Combinado con--distancepara calcular el punto de conexión cuando--to-pointno se da. -
--distance <px>: se extiende el dedo parapinch/stretch, o la distancia de deslizar el dedo en píxeles. -
--hold-ms <ms>— Mantenga presionados los contactos antes de levantar (tiempo de espera de presión larga; el valor predeterminado es de 500 ms paralong-presscuando no se establece). -
--duration-ms <ms>— Tiempo de deslizamiento para mover gestos (deslizar/reducir/estirar; valor predeterminado 300). -
--fingers <n>— Número de contactos (1–10; valor predeterminado 1).pinch/stretchuse siempre 2.
Seguridad de inyección.
touchse niega a insertar a menos que se resuelva un identificador de ventana de destino distinto de cero y esa ventana contenga el primer plano; se produce un error cuandono_targetno se puede resolver ninguna ventana,foreground_not_targetsi no se pudo transferir el foco ono_interactive_desktopen un escritorio bloqueado o seguro. Cada coordenada (centro de elementos, puntos de referencia explícitos--at/--to-pointy generados) se comprueba en el rectángulo de la ventana de destino; un punto fuera de la ventana se muestra como una advertencia no grave (unawarnings[]entrada en--jsono una línea de advertencia en modo de texto) y la inyección continúa, que coincide con los verbos del mouse (click/drag/hover/scroll), que también se insertan en coordenadas fuera de la ventana.--fingerspor encima de 10 se rechaza por adelantado.Nota de hardware. Touch prefiere el dispositivo de puntero sintético moderno (
CreateSyntheticPointerDevice(PT_TOUCH)) y retroceda a la API heredadaInitializeTouchInjection/InjectTouchInput. Si la inserción no se admite en el dispositivo o sesión actual, el comando muestra el código de error de Win32 real (por ejemplo, "no compatible") en lugar de notificar un falso éxito, tratar una salida distinta de cero como "touch not delivered".Escritorio remoto/sesiones de máquina virtual. En un Escritorio remoto (RDP) o algunas sesiones de máquina virtual, el sistema operativo puede aceptar la entrada táctil sintética (salida 0) sin que llegue realmente a la aplicación de destino. Cuando se detecta una sesión remota,
touchanexa una advertencia de incertidumbre de entrega , unawarnings[]entrada en--jsono una línea de advertencia en modo de texto. Una ✅/exit 0 significa que la llamada de inserción se realizó correctamente, no que la aplicación recibió la entrada; confirme el efecto conui screenshot/ui inspectcuando sea importante.
bolígrafo
Inserte la entrada de lápiz sintético/lápiz ( pulsaciones y trazos de lápiz) mediante la API de puntero sintético () de Windows (CreateSyntheticPointerDevice(PT_PEN); Windows 10 1809+). Dirija un centro de elementos, un punto explícito --at o un trazo de lápiz completo --path .
winapp ui pen canvas-1a2b -a myapp # pen tap at the element center
winapp ui pen -a myapp --at 320,240 --pressure 0.8 # firm pen tap at explicit coords
winapp ui pen -a myapp --path "100,100 150,120 210,140 260,120" # draw an ink stroke
winapp ui pen -a myapp --path "100,100 260,100" --eraser # erase along a stroke
winapp ui pen -a myapp --at 200,200 --tilt-x 30 --tilt-y -15 # tilted pen contact
Opciones:
-
--at <x,y>— Punto de contacto de lápiz (coordenadas de pantalla). El valor predeterminado es el centro de elementos del selector. Se omite cuando--pathse da. -
--path "<x,y x,y …>"— Ruta de trazos de lápiz como pares separados porx,yespacios en blanco (una ruta de acceso de un punto es una pulsación). -
--pressure <0.0–1.0>— Presión del lápiz (valor predeterminado 0,5). -
--tilt-x <deg>/--tilt-y <deg>— Ángulos de inclinación del lápiz, -90 a 90 (valor predeterminado 0). -
--eraser— Use el extremo del borrador del lápiz en lugar de la punta. -
--duration-ms <ms>— Tiempo total de desplazamiento de trazo en milisegundos distribuidos como marcos UPDATE interpolados en la ruta de acceso (valor predeterminado: ~10 ms por punto de acceso). Úselo para controlar la rapidez con la que el lápiz se mueve de principio a fin.
Seguridad de inyección. Al igual
touchque ,pense niega a insertar sin una ventana de destino en primer plano no cero (no_target/foreground_not_target/no_interactive_desktop) y comprueba cada punto de entrada de lápiz en el rectángulo de la ventana de destino, que muestra cualquier coordenada fuera de la ventana como una advertencia no irrecuperable (warnings[]en--json, o una línea de advertencia en modo de texto) mientras sigue insertando, coherente con los verbos del mouse. No válido--pressure(fuera de 0,0–1,0) o inclinación (fuera de ±90°) se rechazan por adelantado.Escritorio remoto/sesiones de máquina virtual. El enrutamiento del lápiz es especialmente poco confiable sobre Escritorio remoto: la llamada de inyección puede notificar el éxito (salida 0) mientras que ninguna entrada del lápiz llega a la aplicación. Cuando se detecta una sesión remota,
penanexa una advertencia de incertidumbre de entrega (warnings[]en--jsono una línea de advertencia en modo de texto), por lo que ✅ no se equivoca para la entrega confirmada. Valide los flujos dependientes del lápiz en un escritorio local e interactivo.
mantener el puntero
Mueva el mouse al centro de un elemento para desencadenar efectos de desplazamiento (información sobre herramientas, controles flotantes, estados visuales). Utiliza SendInput para el movimiento realista del mouse con un pequeño botón de alternancia y, a continuación, espera un tiempo de permanencia configurable.
winapp ui hover btn-info-a1b2 -a myapp # hover with default 800ms dwell
winapp ui hover btn-info-a1b2 -a myapp --dwell-time 1200 # longer dwell for slow tooltips
winapp ui list-windows -a myapp # use the main window's HWND below
winapp ui hover btn-info-a1b2 -a myapp; winapp ui screenshot -w <hwnd> --capture-screen # hover then capture tooltip in place
Opciones:
-
--dwell-time <ms>— Tiempo en milisegundos para esperar después de mantener el puntero para que aparezcan efectos (valor predeterminado: 800, intervalo: 0–10000)
send-keys
Enviar entrada de teclado sintético: el homólogo del teclado a click. UIA no tiene ningún patrón de inyección de teclado, por lo que esto cae a la capa win32. Úselo para la navegación por teclado (flechas, Tabulación, Entrar, Esc), métodos abreviados (ctrl+c, alt+f4) y escribir en controles que necesitan eventos de pulsación de tecla en lugar set-valuede escritura atómica.
winapp ui send-keys "down down enter" -a myapp # arrow navigation then commit
winapp ui send-keys "ctrl+a delete" -a myapp # select all, then delete
winapp ui send-keys "Hello world" --target txt-name-a1b2 -a myapp # focus a field, then type text
winapp ui send-keys "text=down text=down text=enter" -a myapp # type the words, don't press the keys
winapp ui send-keys "down down enter" -a myapp --verbatim # same, but type the whole argument literally
winapp ui send-keys "alt+f4" -a myapp # close window via accelerator
winapp ui send-keys "vk=0x5D" -a myapp # a key with no friendly name (Apps/Menu key)
winapp ui send-keys "ctrl+shift+t" -a myapp --via send-input # use OS-wide injection instead of PostMessage
winapp ui send-keys "win+shift+v" -a myapp --via send-input --allow-system-keys # opt in to drive a global hotkey
winapp ui send-keys "ctrl+capslock+f12" -a myapp --via send-input # Narrator command: toggle developer mode
Gramática clave (tokens separados por espacios en blanco, comillas de cadenas de varios tokens):
-
Claves con nombre:
enter/return,tab, ,esc/escapespace,backspacedelete/delinserthomeendpageup/pguppagedown/pgdnup/down/left/right, ,f1f16apps, , , .printscreencapslock -
Secuencias : se presionan varios tokens en orden:
down down enter. -
Combos modificadores :
ctrl,shift,alt,winunidos a+:ctrl+shift+t,alt+f4. Un token que comienza con un modificador pero tiene un segmento desconocido antes del último (ctrl+a+b) es un error; usetext=o--verbatimpara escribirlo. -
Comandos del lector de pantalla : mantenga presionado
capslockoinsert(aliasins), la tecla Narrador, NVDA y JAWS:ctrl+capslock+f12alterna el modo de desarrollador del narrador. Requiere--via send-input, porque los lectores de pantalla no reciben claves publicadas. Si no se está ejecutando ningún lector de pantalla, mantenercapslockactivada o desactivada las mayúsculas y el comando advierte; mantenga presionadoinsertpara evitarlo. -
Texto literal : cualquier token que no sea una clave conocida tiene un carácter de tipo por carácter:
hello. Las palabras literales adyacentes mantienen el espacio entre ellos, por lo que una frase entre comillas como"Hello world"se escribe textualmente (se conserva el espacio); un literal que simplemente contiene+comoC++oa+bse escribe como texto, no analizado como un combo. -
Escape literal explícito : prefijo un token con
text=para escribirlo textualmente incluso cuando entra en conflicto con un nombre clave o modificador:text=enterescribe la palabra "entrar" en lugar de presionar Entrar ytext=ctrl+aescribe la cadena literal. Refleja elvk=escape; el valor de escape todavía se combina con palabras literales adyacentes (text=down low→ "baja"). Dado que los tokens se dividen en espacios en blanco (y los literales adyacentes se vuelven a combinar con un solo espacio), use escapes de barra diagonal inversa dentro de untext=valor para escribir espacios en blanco que no sobrevivirían de otra manera:\s→ espacio,\t→ pestaña,\n→ nueva línea,\r→ nueva línea,\\→ barra diagonal inversa literal.\n,\ry\r\ncada una insertan un único salto de línea (un valor Enter /VK_RETURN), por lo quetext=line1\nline2text=line1\r\nline2y ambos escriben una nueva línea. Por lo tantotext=a\s\sb, escribe "a b" (doble espacio) ytext=\shimantiene un espacio inicial. Un escape no reconocido (por ejemplo,\x) se deja textualmente. -
Literal de argumento completo (
--verbatim): cuando toda la carga es texto literal, pase--verbatimen lugar de escapar cada token context=. Escribe el argumento de claves completa exactamente como se indica ( sin clave con nombre/combinación/vk=/text=interpretación) y, a diferencia de la ruta de acceso normal, conserva el espacio en blanco interno exacto (sin contraer) sin necesidad de .\sPor lo tantosend-keys "down down enter" --verbatim, escribe las palabras ysend-keys "a b" --verbatimmantiene el doble espacio. Los escapes de barra diagonal inversa no se descodifican en--verbatimmodo (se\sescribe como barra diagonal inversa y "s"); use untext=token cuando necesite un carácter de control con escape. -
Claves virtuales sin formato:
vk=0xNN(hexadecimal) ovk=NN(decimal) para las claves sin un nombre descriptivo.
Opciones:
-
--target <selector>: centre este elemento (a través de UIA) antes de enviar claves. Sin ella, las claves van al elemento centrado actualmente de la aplicación. -
--verbatim: escriba el argumento de claves completa como texto literal (sin key/combo/vk=/text=parsing) y conserve el espacio en blanco exacto. Forma de argumento completo del escape por tokentext=. -
--via <transport>—post-message(valor predeterminado) envía entradasWM_KEYDOWN/WM_KEYUP/WM_CHARa la cola de la ventana de destino. Es HWND-targeted y omite UIPI (funciona en niveles de integridad).send-inputinserta todo el sistema operativo a travésSendInputde y va a la ventana de primer plano.
Elección de un transporte o límites conocidos:
-
post-messagees el valor predeterminado porque omite UIPI y no depende de que la ventana esté en primer plano. Límites: no puede desencadenar teclas de acceso rápido globales registradas a travésWH_KEYBOARD_LLde enlaces de bajo nivel (los que pulsan la entrada ascendente de cualquier cola de ventanas) y las aplicaciones que leen el estado de la clave sin procesar a travésGetAsyncKeyStatede pueden no observar modificadores mantenidos. Resuelve y publica automáticamente la ventana secundaria centrada del subproceso de destino (a travésGetGUIThreadInfode ) después del primer plano, por lo que las aplicaciones clásicas win32/WinForms cuyos controles son ventanas secundarias independientes reciben claves sin tener como destino manualmente el control. Las aplicaciones winUI 3/UWP tienen controles XAML sin ventana sin HWND, por lo que un publicadoWM_CHAR/WM_KEYDOWNno tiene nada en el que aterrizar y se quita: el mensaje posterior no puede conducirlos (el comando advierte y sale 0); usa--via send-input. (WPF ventanas son de un solo HWND y las claves de ruta al elemento centrado internamente, por lo que el mensaje posterior funciona allí). -
send-inputgenera una entrada totalmente real (modificadores visibles paraGetAsyncKeyState, desencadena enlaces de bajo nivel), pero va a cualquier ventana en primer plano y está bloqueado por UIPI al insertar desde un proceso con privilegios elevados en un destino de integridad inferior (AppContainer/AppX). Sisend-inputnotifica un error, es probable que el destino sea elevado o una aplicación AppX, usepost-messageo ejecute la CLI en un nivel de integridad coincidente. Como protección de seguridad,send-inputcomprueba que la ventana de destino se encuentra en primer plano inmediatamente antes de insertar y generar un error (foreground_not_target) en lugar de escribir en la ventana incorrecta si no se pudo traer el foco a ella, centrar o hacer clic en la ventana en primer lugar. En un escritorio bloqueado o seguro se produce un error en su lugar conno_interactive_desktop(no existe ninguna ventana de primer plano para insertar en): desbloquee la sesión o use un verbo de patrón UIA (set-value,invoke). -
Los combos reservados por el sistema (
win+l,win+r, ,ctrl+shift+escctrl+alt+delalt+tabalt+f4ctrl+esclonewin/printscreen, ...) actúan en el sistema operativo o shell en lugar de solo el destino cuando se envía el sistema operativo en todo el mundo.send-inputlos rechaza de forma predeterminada (errores coninvalid_argumentsy no envía nada) porque insertarlos en el nivel del sistema operativo tiene efectos mucho más allá de la ventana de destino (por ejemplo,win+lbloquearía la sesión). Pasar--allow-system-keyspara participar: esto le permite conducir una tecla de acceso rápido global, como PowerToys'win+shift+vowin+r(el enlace global de bajo nivel supervisa el flujo de entrada de todo el sistema operativo, por lo que el combo insertado lo activa). Excepciones que permanecen bloqueadas incluso con--allow-system-keys:win+lbloquea la estación de trabajo a travésLockWorkStation()de la cual no se puede recuperar de la automatización (interrumpe las sesiones de CI y escritorio remoto), yctrl+alt+deles una secuencia de atención segura (SAS) que Windows quita de la entrada insertada independientemente de la marca , nunca puede surtir efecto, por lo que los errores (invalid_arguments, salida 1) en lugar de notificar un éxito engañoso. Otros combos (alt+f4,ctrl+shift+esc,win+r, ...) se permiten con la marca — el llamador tenga cuidado. Como alternativa, para entregar un combo del sistema a una ventana específica,--via post-messageque tiene ámbito de ventana y no se ve afectado (un publicado es inofensivo, aunque un publicadowin+lalt+f4todavía cierra la ventana de destino).
Eventos por pulsación de tecla (KeyDown /TextChanged):
-
Las teclas con nombre y los combos modificadores (
down,enter,ctrl+shift+t)vk=0xNNactivan un valor realKeyDown(yKeyUp) en ambos transportes, se entregan como eventos discretosWM_KEYDOWN/WM_KEYUP(oSendInputde clave virtual). -
El texto con tipo literal (
hello) difiere según el transporte:-
--via send-inputasigna cada carácter a su tecla virtual (más Mayús) en el diseño de teclado activo, por lo que el destino ve un originalKeyDowncon la tecla virtual correcta seguida de la OS compuestaWM_CHAR(elevandoTextChanged) , es decir, una pulsación de tecla completa por carácter. Los caracteres no accesibles en el diseño actual (o que necesiten Ctrl/AltGr) vuelvan a un paquete Unicode para que el carácter exacto siga aterrizando. Usasend-inputcuando necesites fidelidad de pulsación de teclaKeyDown(por ejemplo, conducir winUI 3 /WPFTextBoxcuyos controladores desactivenKeyDown). En el caso de un host de prueba de WinUI 3 normal (sin privilegios elevados), traiga su ventana al primer plano (winapp ui focus/al hacer clic en él), ya quesend-inputtiene como destino la ventana de primer plano. -
--via post-messagepublica un soloWM_CHARpor carácter ( no publicaWM_KEYDOWN/WM_KEYUPpara el texto escrito; están reservados para teclas o combinaciones con nombre), que no genera un carácter por carácterKeyDown. Se vuelve a colocar automáticamente en el control secundario centrado de la ventana, por lo que los controles de edición controlados por Win32/WinFormsWM_CHARclásicos llegan al texto (elevandoTextChanged). Advertencia: WinUI 3 / UWP / aplicaciones XAML (destino principal de winapp) tienen controles sin ventana que ignoran publicadosWM_CHAR/WM_KEYDOWN, por lo que ni el texto literal ni las claves con nombre (Entrar, dígitos, ...) llegan a ellos, aunque el comando notifica que se ha realizado correctamente. Emite una advertencia cuando el destino es similar a XAML y sigue saliendo de 0 (PostMessagese desencadena y olvida y no puede confirmar la entrega). Usa--via send-inputpara controlar aplicaciones WinUI 3/ UWP o WPF; reservapost-messagepara controles Win32 clásicos o cuando solo lo necesites en los niveles de integridad.
-
Salida JSON (--json): el resultado hwnd es la ventana efectiva a la que se entregaron las claves; para --via post-message esto se trata del control secundario centrado resuelto cuando el comando se vuelve a colocar en él (no necesariamente la ventana de nivel -w/-a/-e superior), por lo que la automatización puede confirmar exactamente dónde se encuentra la entrada. Cuando ese destino efectivo es similar a un host XAML sin ventanas, la advertencia de entrega anterior también se muestra como una warnings[] entrada (el mismo aviso que se muestra en la consola), por lo que una ✅ salida 0 no se equivoca para la entrega confirmada.
set-value
Establezca un valor en un elemento editable mediante programación (sin pulsaciones de tecla, sin primer plano de la aplicación). Usa una cadena de reserva:
- ValuePattern : controles TextBox, ComboBox, PasswordBox y la mayoría de los controles editables.
- RangeValuePattern : controles numéricos (Slider, ProgressBar) cuando el valor analiza como un número.
-
LegacyIAccessible (
IAccessible::put_accValue): la reserva para los controles de edición de solo TextPattern que no exponen valuePattern (por ejemplo, cuadros rich-edit/Documentcompose). Esto cierra la brecha de lectura y escritura en la queget-valuepodría leer este control, peroset-valueno pudo hacerlo.
winapp ui set-value txt-textbox-a4b1 "Hello world" -a notepad
winapp ui set-value sld-volume-b2c3 75 -a myapp
winapp ui set-value doc-compose-9f3a "hello" -a myapp # RichEdit/compose box via LegacyIAccessible
Si ninguno de los tres patrones puede establecer el valor, set-value se produce un error claro que apunta a send-keys como último recurso.
No todos los editores enriquecidos admiten conjuntos de programación. La reserva LegacyIAccessible solo funciona en controles cuya accesibilidad implementa: los controles nativos
IAccessible::put_accValuede edición enriquecida win32 y las superficies de redacción Chromium/Electron/WebView2 normalmente lo hacen. WinUI 3RichEditBoxy WPFRichTextBoxno admiten la configuración de valores mediante programación; por diseño, exponen su contenido a Automatización de la interfaz de usuario como de solo lectura (patrón de texto, sin patrón de valor configurable), por lo queset-valueno pueden escribir en ellos. Usesend-keys(que necesita un escritorio en primer plano desbloqueado) para esos.
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": "..." }
winapp ui get-value SearchBox -a myapp --json
winapp ui wait-for SearchBox -a myapp --value "" --timeout 5000
Un campo de texto vacío leído correctamente devuelve "text": "", no su etiqueta de accesibilidad. El contenido de solo espacio en blanco también se conserva en JSON.
wait-for --value "" coincide con un campo vacío, tanto si está fresco como si se ha borrado después de la edición. Para leer la etiqueta de accesibilidad en su lugar, use get-property --property Name.
enfoque
winapp ui focus txt-textbox-a4b1 -a notepad
Activa la ventana del control seleccionado cuando es necesario y, a continuación, centra el control.
El selector es obligatorio; use -a <app> o -w <HWND> para elegir el destino.
Correcto significa que la ventana estaba en primer plano y el control seleccionado se confirmó HasKeyboardFocus antes de que se devolva el comando. El comando permite hasta 500 ms para que el control notifique el foco; se detiene si el destino desaparece o pierde el primer plano en lugar de intentar recuperar el foco. Un cuadro de diálogo de propiedad delante de la ventana principal no es suficiente: seleccione un control en el cuadro de diálogo si es el destino.
Este comando necesita un escritorio interactivo desbloqueado y no omite Windows restricciones de activación. Si se produce un error con foreground_not_target, active manualmente la ventana prevista y compruebe si hay un cuadro de diálogo de bloqueo antes de volver a intentarlo.
Para focus_not_acquired, inspeccione la interfaz de usuario actual y elija un control enfocado.
Para stale_element, vuelva a detectar el destino con inspect o search.
Mantenga el mismo --on destino en los comandos de detección y reintento.
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
# Synthesize real mouse-wheel input over the element (1 = one notch up, -1 = one notch down).
# Use this to test handlers that respond to the wheel directly (zoom, custom scroll) rather than ScrollPattern.
winapp ui scroll img-map-a1b2 --wheel -1 -a myapp
Opciones:
-
--direction <up|down|left|right>— Desplácese incrementalmente a través deScrollPattern. -
--to <top|bottom>— Vaya al principio o al final a través deScrollPattern. -
--wheel <notches>— Sintetiza la entrada de la rueda del mouse sobre el centro del elemento a travésSendInputde , en notillas de rueda (detents):1= una nota arriba/lejos,-1= una notch hacia abajo/hacia,3= tres pulgadas hacia arriba. (Cada notch es el WindowsWHEEL_DELTAde 120 unidades queSendInputconsume; la CLI escala los notches en 120 por usted). OmiteScrollPattern.
--direction,--toy--wheelson mutuamente excluyentes: pasan exactamente uno. Dado--wheelque inserta la entrada en todo el sistema operativo en las coordenadas de la pantalla, lleva primero el destino al primer plano y produce un error (foreground_not_target) si no se pudo transferir el foco, en lugar de desplazarse por la ventana incorrecta.
get-focused
winapp ui get-focused -a myapp
winapp ui get-focused -w <HWND> --json
Muestra el elemento que actualmente tiene el foco de teclado en la aplicación seleccionada, incluidos los controles cuya propiedad de la aplicación solo está disponible a través de su ventana primaria.
Con -w, el foco debe pertenecer a esa ventana, no a otra ventana o a un elemento emergente propiedad en el mismo proceso. Con -a, se incluyen otras ventanas del proceso seleccionado.
La salida JSON tiene hasFocus:false cuando no se puede comprobar ningún elemento centrado como perteneciente al destino. Si se produce un error en una consulta de foco o propiedad de ventana, el comando sale distinto de cero; vuelva a intentar get-focusedy vuelva a detectar la ventana con list-windows si se ha cerrado.
list-windows
Enumere todas las ventanas visibles para una aplicación, incluidas las ventanas emergentes y los cuadros de diálogo. De forma predeterminada, se excluyen las ventanas sin título con tamaño cero (ventanas del sistema invisible).
winapp ui list-windows -a imageresizer
winapp ui list-windows -a Terminal
winapp ui list-windows # all windows (no filter)
winapp ui list-windows --show-hidden # include invisible zero-size windows
rendimiento
Libere la interfaz de usuario de este flujo de trabajo temprano en lugar de esperar la gracia de inactividad de cuatro segundos. Requiere WINAPP_UI_WORKFLOW_ID; no toma ninguna aplicación y ningún selector. Consulta Liberar el turno temprano.
winapp ui yield
winapp ui yield --json # {"released": true} — or false when nothing was held
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 | ❌ | ✅ |
¹ set-value funciona en cualquier control que exponga ValuePattern/RangeValuePattern, además de controles de edición de solo TextPattern cuya accesibilidad implementa IAccessible::put_accValue (reserva LegacyIAccessible).
WinUI 3 RichEditBox y WPF RichTextBox son excepciones: solo exponen el patrón text de solo lectura (no se puede establecer el patrón valor), por lo que no se pueden establecer mediante programación mediante diseño; use send-keys (se requiere escritorio interactivo) para escribir en ellos.
Uso del motor desde su propio código
Todo winapp ui está disponible como una biblioteca, por lo que puede controlar la misma automatización desde una prueba o herramienta sin shell hacia la CLI:
| Package | Lo que agrega |
|---|---|
Microsoft.Windows.SDK.BuildTools.WinApp.UIAutomation |
Inspección, selectores, interacción del patrón UIA, inyección de entrada, capturas de pantalla |
Microsoft.Windows.SDK.BuildTools.WinApp.UIAutomation.Recording |
Grabación de vídeo en MP4, más paquetes de fotogramas |
var services = new ServiceCollection().AddLogging().AddWinAppUiAutomation().BuildServiceProvider();
var ui = services.GetRequiredService<IUiAutomation>();
var target = UiTarget.FromWindowHandle(myWindowHandle);
var save = await ui.FindSingleElementAsync(target, new UiSelector { Query = "Save" }, default);
await ui.InvokeAsync(target, save!, default);
Para acciones deterministas, use la sobrecarga que toma UiInvokeAction:
var selected = await ui.FindSingleElementAsync(
target, new UiSelector { Query = "Save" }, requireUnique: true, default);
if (selected is null) throw new InvalidOperationException("Save was not found.");
UiInvokeActionResult result = await ui.InvokeAsync(target, selected, UiInvokeAction.Invoke, default);
requireUnique: true rechaza texto ambiguo en lugar de elegir una coincidencia invocable. Las coincidencias de AutomationId exactos tienen prioridad sobre los subcadenas name o AutomationId; Un nombre único todavía puede seleccionar un control cuyo AutomationId se comparte.
Para un destino con ámbito de aplicación, esa comprobación cubre todas sus ventanas de aplicación o propiedad. Use -w <HWND> (o un destino de biblioteca de ventana explícita) para restringir el ámbito de selección.
Devuelve Pattern y PerformedAction con los mismos significados que el resultado de la acción de la CLI.
Pase un elemento devuelto por inspección o selección, con su slug en tiempo de ejecución o automationId único intacto. Las acciones explícitas rechazan una identidad que falta o ambigua en lugar de volver a enlazar por nombre y tipo de control.
Para las lecturas con ámbito, establezca en UiSelector.Root otra UiSelector, ControlType en un nombre de tipo y ClassName en la clase de proveedor literal. Usan los mismos predicados de consulta que la CLI. Solo se admite un nivel raíz: selector.Root.Root debe ser null. Una raíz anidada produce ArgumentException antes de buscar la ventana de destino. Use un automationId o slug raíz único en lugar de anidar selectores raíz.
UiControlTypes.GetId(name) resuelve los nombres de tipo oficiales y los dos alias documentados, que devuelven 0 un nombre no válido.
UiControlTypes.GetName(id) devuelve el nombre canónico o Unknown(id) para un identificador no reconocido.
Al pasar un UiElement objeto restaurado de JSON a GetTextAsync o GetPropertiesAsync, mantenga sus Selector y WindowHandle. Un selector de slug debe seguir identificando el elemento original; Si ya no existe, estas lecturas inician UiElementNotFoundException en lugar de seleccionar otro elemento con el mismo automationId o nombre. Vuelva a ejecutar la consulta original para actualizar el resultado. Las lecturas con ámbito también propagan errores de captadores generales de propiedades UIA y patrones UIA adquiridos en lugar de devolver valores NULL o un valor capturado previamente.
La grabación es un paquete independiente para que los proyectos que solo inspeccionen y impulsen la interfaz de usuario no extraen SkiaSharp. El paquete de automatización tiene como destino y net10.0-windowsnet10.0-windows10.0.19041.0; este último agrega Windows captura de gráficos, que es lo que permite screenshot capturar windows ocluidas o compuestas por GPU. Consulte el archivo Léame de cada paquete en NuGet para obtener la API completa y el equilibrio de la plataforma de destino.
UiTarget.FromWindowHandle es el punto de entrada para marcos de prueba que ya le entregan una ventana , por ejemplo MSTest.Windows.UIAutomation, cuyo WindowTest.MainWindow es un puente UIA2 AutomationElement a través de con MainWindow.Current.NativeWindowHandle.
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 | La captura predeterminada es por ventana y no incluye superposiciones noowned | Siga el flujo de trabajo de superposición de captura de pantalla para seleccionar una ventana con -w <hwnd> --capture-screen |
foreground_not_target de --capture-screen |
Windows rechazó la activación, por lo que una captura de pantalla habría grabado cualquier ventana que esté realmente delante | Haga clic en la ventana de destino o cierre la ventana de robo de foco y vuelva a intentarlo o quite. --capture-screen |
element_not_found durante el registro |
Selector especificado, pero sin elemento coincidente | Volver a ejecutar inspect o search para obtener un selector nuevo |
| WGC no disponible durante el registro | Error de inicialización de captura de WGC; no hay reserva silenciosa | Comprobar GPU/controlador; usar --capture-screen para dar su consentimiento a la captura de dc de pantalla |
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 list-windows -a myapp # use the main window's HWND below
winapp ui set-value txt-searchbox-e5f6 "query" -a myapp; winapp ui screenshot -w <hwnd> --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--jsonsearch(wait-foro ) y devuelve el{ "matchCount": 0, ... }.{ "found": false, "timedOut": true, ... }Stderr 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)" }
# Read typed element state while preserving the legacy string property map
$property = winapp ui get-property "Counter Display" -a $pid --json | ConvertFrom-Json
if ($property.element.type -ne "Text") { throw "Unexpected type: $($property.element.type)" }
if ($property.element.isOffscreen) { throw "Counter is offscreen" }
Los sobres JSON son:
-
inspect:{ "depth", "interactive", "hideDisabled", "hideOffscreen", "windows": [...] } -
search:{ "matchCount", "hasMore", "matches": [...] } -
wait-for:{ "found", "waitedMs", "element"?, "timedOut" } -
get-property:{ "elementId", "element", "properties": { ... } }
Los elementos con tipo usan type y numéricos x, y, widthy height.
La geometría está en píxeles de pantalla físicos.
0,0,0,0es Automatización de la interfaz de usuario rectángulo vacío o no displayed-UI de esta proyección; isOffscreen es independiente, por lo que un elemento offscreen todavía puede tener límites distintos de cero.
Cada inspect --jsonwindows[] entrada y el status --json resultado incluyen windowDpi, scale (windowDpi / 96), dpiAwarenessy coordinateSpace: "physical-screen-pixels". Estos describen el contexto de PPP de la ventana de destino, no la supervisión incondicional de PPP: Windows notifica 96 para una ventana no consciente, ppp del sistema para una ventana compatible con el sistema y ppp de monitor actual para una ventana compatible con el monitor por monitor. Si no se puede leer el contexto de HWND o PPP, se produce un error en el comando en lugar de sustituir silenciosamente 96. Cuando status resuelve un proceso antes de que tenga una ventana de nivel superior, hwnd es 0 y los campos de PPP se omiten hasta que exista una ventana. Para todo inspectel proceso, la ventana de destino seleccionada sigue siendo rápida; si una ventana emergente posterior desaparece después de que se leyó su árbol, su windows[] entrada lleva dpiError y omite los campos de PPP mientras todavía se devuelven los árboles de ventana restantes.
Consulte las aptitudes references/ui-json-envelope.md enviadas winapp-ui-automation para obtener ejemplos completos de cada sobre.
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