Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Inspecionar e interagir com aplicações Windows em execução a partir da linha de comandos. Usado por agentes e programadores de IA para testes de interface, depuração e automação.
Descrição geral
winapp ui fornece comandos para inspecionar e interagir com Windows interfaces de aplicação.
Utiliza Windows Automatização da Interface de Utilizador (UIA). Funciona com qualquer aplicação Windows — WPF, WinForms, Win32, Electron e WinUI 3.
A maioria dos comandos conduz a aplicação através de padrões UIA (sem injeção de entrada); ui click é a exceção e usa simulação real de rato para controlos que não suportam InvokePattern.
Início Rápido
# 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
Aplicações de Segmentação
Por nome do processo
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 da janela
winapp ui inspect -a "LICENSE - Notepad"
winapp ui inspect -a "Fix WinApp" # partial title match
Por PID
winapp ui inspect -a 12345
Por HWND (estável — sobrevive a alterações de tab/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
Usar -a para descoberta, -w para direcionamento estável. Quando -a corresponde a várias janelas, o comando lista-as com HWNDs para escolheres.
Selecionadores
Elementos-alvo usando o seletor mostrado [brackets] na saída de inspecção/pesquisa.
Existem três tipos de selecionadores:
| Selector | Significado | Example |
|---|---|---|
MinimizeButton |
AutomationId (mostrado quando único — estável, preferencial) | winapp ui invoke MinimizeButton -a myapp |
btn-close-d1a0 |
Slug semântico (mostrado quando não existe um Automation Id único) | winapp ui invoke btn-close-d1a0 -a myapp |
Submit |
Pesquisa em texto simples contra Name/AutomationId (substring insensível a maiúsculas minúsculas) | winapp ui invoke Submit -a myapp |
Os seletores AutomationId são identificadores de conjunto de programadores (AutomationProperties.AutomationId em XAML).
Quando um AutomationId é único em toda a árvore da interface e inspectsearch o mostra diretamente como seletor — estes sobrevivem a alterações de layout, localização e reestruturação da árvore.
Os seletores de slug (por exemplo, btn-close-d1a0) são gerados quando não existe um AutomationId único.
Formato: prefix-name-hash. O hash valida a identidade do elemento, mas pode ficar obsoleto após alterações na interface.
Inspeção do formato de saída
O inspect comando mostra a árvore de elementos com saída colorida (seletor em ciano, nome em verde, metadados em cinzento):
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
A primeira palavra em cada linha é o seletor — usa-o com outros ui comandos.
Quando um elemento tem um AutomationID único, é usado diretamente (por exemplo, TabView, NewTabButton).
Quando não existe um AutomationId único, é usado um slug gerado (por exemplo, tab-newtab-5f5b).
Slugs semânticos
As lesmas usam o formato: prefix-normalizedname-hash onde:
- Prefixo — Abreviatura de tipo de 3 letras (BTN, TXT, CHK, CMB, ITM, TAB, IMG, LBL, PN, WIN, GRP, LNK, MNU, ETC.)
- normalizedname — alfanumérico minúsculo de AutomationId (preferido) ou Name, máximo 15 caracteres
- hash — hash hexadecimal de 4 caracteres do RuntimeId do elemento (valida a identidade do elemento)
As lesmas são seguras contra conchas (sem caracteres especiais), únicas e podem ser usadas diretamente como argumentos. O hash fornece deteção de estagnação — se o elemento foi substituído, obtém: "O elemento pode ter mudado. Inspecionar novamente."
Elementos sem nome ou AutomationId mostram apenas prefixo + hash (por exemplo, pn-c8a3).
Desambiguação de múltiplos combates
Os slugs da inspect/search saída são únicos, mas podem mudar por alterações de layout – use-os em vez de nomes de tipos simples ou texto quando há múltiplas correspondências. Quando um seletor é ambíguo, o CLI imprime todas as correspondências com os seus slugs para que possas escolher o certo e voltar a executar com esse 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
Pesquisa de texto simples
Use texto simples para procurar elementos — sem necessidade de sintaxe especial:
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
Quando uma pesquisa de texto corresponde a vários elementos (por exemplo, SettingsExpander onde Group, Button e Text partilham o mesmo nome), a CLI escolhe automaticamente o único elemento invocável. Se vários forem invocáveis, lista todas as correspondências com slugs.
Para resultados de pesquisa não invocáveis (por exemplo, um TextBlock dentro de um Botão), a pesquisa revela automaticamente o ancestral invocável mais próximo — o elemento pai que pode usar com invoke.
Isto funciona para todos os seletores de pesquisa:
lbl-savechanges-a1b2 "Save changes" (120,40 80x20)
^ invoke via: btn-save-c3d4 "Save"
O seletor de superfície pode ser usado diretamente:
winapp ui invoke btn-save-c3d4 -a myapp # invoke the parent Button
Comandos
estado
Liga-te a uma aplicação e mostra as informações de ligação.
winapp ui status -a notepad
winapp ui status -a notepad --json
inspecionar
Veja a árvore de elementos da interface. A saída mostra slugs semânticos com indentação de 2 espacios para hierarquia:
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
Exemplo de saída (padrão):
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)
Saída de exemplo (--interactive — apenas elementos invocáveis, 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)
Os elementos podem mostrar estes marcadores de estado:
-
[on]/[off]/[indeterminate]— estado toggle/checkbox -
[collapsed]/[expanded]— expandir/colapsar o estado para árvores, caixas de combo, itens do menu -
[scroll:v]/[scroll:h]/[scroll:vh]— contentor rolável (vertical, horizontal ou ambos) -
[offscreen]— elemento não é visível no ecrã -
[disabled]— elemento não está ativado -
value="..."— conteúdo textual atual para elementos editáveis (quando diferente do Nome)
pesquisa
Encontre elementos que correspondam a um seletor. A saída mostra 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
Exemplo de saída:
btn-minimize-d1a0 "Minimize" (1222,206 48x48)
btn-maximize-e2b1 "Maximize" (1270,206 48x48)
btn-close-d1a2 "Close" (1318,206 48x48)
Slugs mostrados na saída (por exemplo, btn-minimize-d1a0) podem ser usados diretamente com outros comandos:
winapp ui invoke btn-minimize-d1a0 -a notepad
get-property
Leia os valores das propriedades a partir de um elemento. Inclui o estado específico do padrão (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 ecrã
Captura uma janela ou elemento como PNG. Quando existem várias janelas (por exemplo, app + diálogo aberto), são compostas numa única PNG com cada janela costurada.
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)
Quando os diálogos ou pop-ups estão abertos, todas as janelas são compostas numa só PNG para que possas ver o estado completo da interface numa única imagem.
Usa --capture-screen quando precisares de capturar menus pop-up, menus suspensos, flyouts ou sobreposições de tooltip. No --capture-screen modo (e ao tentar novamente após detetar um frame em branco), a janela alvo é trazida primeiro para o primeiro plano; as capturas normais de janelas não movem a janela.
invocar
Ativar programaticamente um elemento (clicar num botão, alternar uma caixa, expandir a caixa de combo).
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
Tenta padrões por ordem: InvokePattern → TogglePattern → SelectionItemPattern → ExpandCollapsePattern.
clicar
Clica num elemento nas coordenadas do ecrã usando simulação de rato. Use isto para controlos que não suportam InvokePattern (por exemplo, cabeçalhos de colunas, itens 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
valor de conjunto
Defina um valor num elemento editável (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
Leia o valor atual de um elemento. Utiliza uma cadeia de recurso inteligente: TextPattern (RichEditBox, Document) → ValuePattern (TextBox, Slider) → SelectionPattern (ComboBox, RadioButton, TabView) → Nome (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": "..." }
focus
Mude o foco do teclado para um elemento.
winapp ui focus txt-textbox-a4b1 -a notepad
rolar para a vista
Desloca um elemento para a área visível.
winapp ui scroll-into-view itm-targetitem-c3d4 -a myapp
espera-por
Espere que um elemento apareça, desapareça ou que um valor alcance um alvo.
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
Pergaminho
Desloca um elemento de contentor. Encontre recipientes roláveis com search scroll — procure [scroll:v] marcadores (verticais) ou [scroll:h] (horizontais).
# 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
Foca-te
Mostra o elemento que atualmente tem foco no teclado.
winapp ui get-focused -a myapp
janelas de lista
Liste todas as janelas visíveis de uma aplicação, incluindo pop-ups e diálogos.
winapp ui list-windows -a imageresizer
winapp ui list-windows -a Terminal
winapp ui list-windows # all windows (no filter)
Suporte ao Quadro
| Framework | inspecionar | pesquisa | invocar | valor de conjunto | captura de ecrã |
|---|---|---|---|---|---|
| WPF | ✅ Árvore completa | ✅ Todas as propriedades | ✅ Todos os padrões | ✅ | ✅ |
| WinForms | ✅ | ✅ | ✅ | ✅ | ✅ |
| Win32 | ✅ | ✅ | ✅ | ✅ | ✅ |
| WinUI 3 | ✅ | ✅ | ✅ | ✅ | ✅ |
| Elétron | ⚠️ Árvore de crómio | ⚠️ Limitado | ⚠️ Varia | ⚠️ Varia | ✅ |
| Flutter | ⚠️ Básico | ⚠️ Básico | ❌ Minimal | ❌ | ✅ |
Troubleshooting
| Erro | Motivo | Solution |
|---|---|---|
| "Nenhuma aplicação de corrida encontrada" | A aplicação não está a correr ou não corresponde com nomes | Verifique o nome do processo ou use o PID |
| "Múltiplas janelas coincidem" | Valor ambíguo -a |
Utilização -w <HWND> a partir das opções listadas |
| "tem várias janelas" | O processo tem múltiplas janelas | Usar -w <HWND> para atingir um específico |
| "Seletor correspondeu a N elementos" | Seletor legado ambíguo | Use slugs da inspect saída, ou adicione [0], [1] aos seletores legados |
| "O elemento pode ter mudado" | O slug hash não corresponde ao elemento atual | Repetir inspect ou search comprar bales frescas |
| "não suporta qualquer padrão de invocação" | Elemento não pode ser invocado | Use inspect no elemento para encontrar uma criança invocável |
| "Nenhuma janela UIA encontrada" | A UIA não consegue ver o processo | Use list-windows para encontrar o HWND, então -w |
| "Janela tem tamanho zero" | A janela é minimizada | A aplicação será restaurada automaticamente |
| Popup/menu suspenso que não aparece na captura de ecrã | O PrintWindow não capta sobreposições | Usar --capture-screen flag |
Padrões comuns
Navegue e verifique
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
Encontre texto e invoque o seu pai
# 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 ecrã com sobreposições pop-up
winapp ui set-value txt-searchbox-e5f6 "query" -a myapp; winapp ui screenshot -a myapp --capture-screen
Navegar, esperar e verificar (single chain)
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
Descobre, clique e verifique
winapp ui inspect -a myapp --interactive; winapp ui invoke btn-submit-7a90 -a myapp; winapp ui screenshot -a myapp
Interação de diálogo de ficheiros
Os diálogos de abertura/gravação de ficheiros são diálogos padrão do Windows com suporte a 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 identificar as lesmas reais para uma conversa específica.
Porquê ; para encadear (não &&)
O operador do && PowerShell pode congelar quando uma CLI nativa escreve para stderr ou usa sequências de escape ANSI. Use ; em vez disso — executa cada comando incondicionalmente e evita este bloqueio. Isto também é melhor para fluxos de trabalho de agentes: normalmente queres que a captura de ecrã seja executada mesmo que o invoke tenha tido uma saída diferente de zero.
Padrões de Teste de IC
Use comandos winapp ui em pipelines CI (GitHub Actions, Azure DevOps) para testes de fumo e validação da interface.
wait-for com --property e --value atua como uma asserção — devolve o código de saída 1 no timeout, falhando automaticamente o passo CI.
Iniciar e testar no GitHub Actions
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
Afirmar o estado do elemento com wait-for
wait-for --value sondagens até que o valor de um elemento corresponda à cadeia esperada, usando o mesmo recurso inteligente que get-value (TextPattern → ValuePattern → SelectionPattern → Name). Devolve o código de saída 0 ao corresponder, o código de saída 1 ao timeout — tornando-o uma afirmação amiga do CI. Use --property para verificar uma propriedade específica da UIA em vez disso.
# 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
Assert com saída JSON
Use --json com PowerShell ou jq para asserções mais complexas:
Contrato de código de saída para
searchewait-forno--jsonmodo: quando nenhum elemento corresponde a (search) ou a espera expira (wait-for), o comando escreve um envelope de resultados totalmente analisável para stdout ({ "matchCount": 0, ... }ou{ "found": false, "timedOut": true, ... }) e retorna o código de saída 1. O Stderr está vazio no--jsonmodo (a saída do logger é suprimida). Desvia nos campos envelope, ou em$LASTEXITCODE, dependendo de qual for mais ergonómico.
# 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)" }
Exemplo de teste completo de fumo
# 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
Windows developer