Automatizace uživatelského rozhraní

Zkontrolujte spuštění Windows aplikací z příkazového řádku a interakci s nimi. Používají se agenti AI a vývojáři pro testování, ladění a automatizaci uživatelského rozhraní.

Přehled

winapp ui poskytuje příkazy pro kontrolu a interakci s uživatelskými rozhraními aplikace Windows. Používá Windows model UI Automation (UIA). Funguje s libovolnou Windows aplikací – WPF (Windows Presentation Foundation), WinForms, Win32, Elektron a WinUI 3. Většina příkazů řídí aplikaci vzory UIA (bez vstupní injektáže); ui click je výjimka a používá skutečnou simulaci myši pro ovládací prvky, které nepodporují InvokePattern.

rychlé zprovoznění

# 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

Cílení aplikací

Podle názvu procesu

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

Podle názvu okna

winapp ui inspect -a "LICENSE - Notepad"
winapp ui inspect -a "Fix WinApp"     # partial title match

Autor: PID

winapp ui inspect -a 12345

Podle HWND (stabilní – přežije změny tabulátoru/názvu)

# 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

Slouží -a ke zjišťování pro -w stabilní cílení. Pokud -a odpovídá více oknům, příkaz je zobrazí se seznamem HWND, které můžete vybrat.

Selektory

Cílové prvky pomocí selektoru zobrazeného ve [brackets] výstupu kontroly a hledání Existují tři typy selektorů:

Selector Význam Example
MinimizeButton AutomationId (zobrazené, pokud je jedinečné – stabilní, upřednostňované) winapp ui invoke MinimizeButton -a myapp
btn-close-d1a0 Sémantická slug (zobrazená v případě, že žádné jedinečné ID automatizace) winapp ui invoke btn-close-d1a0 -a myapp
Submit Vyhledávání ve formátu prostého textu proti name/AutomationId (podřetětět bez rozlišování malých a velkých písmen) winapp ui invoke Submit -a myapp

Selektory AutomationId jsou identifikátory sady vývojářů (AutomationProperties.AutomationId v JAZYCE XAML). Pokud je Id automatizace jedinečné v celém stromu inspect uživatelského rozhraní a search zobrazí ho přímo jako selektor – ty přežijí změny rozložení, lokalizaci a restrukturalizaci stromu.

Selektory slug (např. ) se vygenerují, btn-close-d1a0pokud neexistuje žádný jedinečný identifikátor AutomationId. Formát: prefix-name-hash. Hodnota hash ověří identitu elementu, ale po změně uživatelského rozhraní může být zastaralá.

Kontrola výstupního formátu

Příkaz inspect zobrazí strom elementu s barevným výstupem (selektor v azurové barvě, název zeleně, metadata šedě):

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

První slovo na každém řádku je selektor – použijte ho s dalšími ui příkazy. Pokud má prvek jedinečný AutomationId, použije se přímo (např TabView. , NewTabButton). Pokud neexistuje žádný jedinečný identifikátor AutomationId, použije se vygenerovaný slug (např. tab-newtab-5f5b).

Sémantické slugy

Slugy používají formát: kde: prefix-normalizedname-hash

  • prefix — zkratka typu 3 písmena (btn, txt, chk, cmb, itm, tab, img, lbl, pn, win, grp, lnk, mnu atd.)
  • normalizedname – malá písmena alfanumerická z AutomationId (preferovaný) nebo Název, maximálně 15 znaků
  • hash – šestnáctkový algoritmus 4 char hodnoty runtimeId elementu (ověření identity elementu)

Slugy jsou bezpečné prostředí (bez speciálních znaků), jedinečné a lze je použít přímo jako argumenty. Hodnota hash poskytuje detekci neakutnosti – pokud byl prvek nahrazen, získáte: "Element mohl být změněn. Znovu spusťte kontrolu."

Prvky bez názvu nebo Id automation zobrazují pouze předponu + hash (např. pn-c8a3).

Nejednoznačnost více shod

Slugs from inspect/search output are unique, but can change across layout changes – use them over plain type names or text when multiple matches. Když je selektor nejednoznačný, rozhraní příkazového řádku vytiskne všechny shody s jejich slugy, abyste mohli vybrat ten správný a znovu spustit s tímto slugem.

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

Použití prostého textu k hledání prvků – nevyžaduje se žádná zvláštní syntaxe:

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

Když hledání textu odpovídá více prvkům (například SettingsExpander, kde Group, Button a Text všechny sdílejí stejný název), rozhraní příkazového řádku automaticky vybere jediný vyvoláný prvek. Pokud je více vyvoláno, zobrazí se seznam všech shod se slugy.

Pro nevolitelné výsledky hledání (např. TextBlock uvnitř tlačítka) se při hledání automaticky zobrazí nejbližší vyvoláný nadřazený prvek – nadřazený prvek, se invokekterým můžete použít . To funguje pro všechny selektory vyhledávání:

  lbl-savechanges-a1b2 "Save changes" (120,40 80x20)
        ^ invoke via: btn-save-c3d4 "Save"

Selektor povrchu lze použít přímo:

winapp ui invoke btn-save-c3d4 -a myapp    # invoke the parent Button

Commands

stav

Připojte se k aplikaci a zobrazte informace o připojení.

winapp ui status -a notepad
winapp ui status -a notepad --json

Zkontrolovat

Zobrazte strom prvků uživatelského rozhraní. Výstup zobrazuje sémantické slugy s odsazením mezer pro hierarchii:

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

Příklad výstupu (výchozí):

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)

Příklad výstupu (--interactive – pouze vyvolání prvků, plochý seznam):

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)

Prvky můžou zobrazovat tyto značky stavu:

  • [on] / [off] / [indeterminate] — přepínací/zaškrtávací políčko
  • [collapsed] / [expanded] — rozbalení/sbalení stavu pro stromy, pole se seznamem, položky nabídky
  • [scroll:v] / [scroll:h] / [scroll:vh] — posuvný kontejner (svislý, vodorovný nebo oba)
  • [offscreen] — prvek není na obrazovce viditelný.
  • [disabled] — prvek není povolen.
  • value="..." — aktuální textový obsah pro upravitelné prvky (pokud se liší od názvu)

Vyhledání prvků odpovídajících selektoru Výstup ukazuje sémantické slugy:

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

Příklad výstupu:

  btn-minimize-d1a0 "Minimize" (1222,206 48x48)
  btn-maximize-e2b1 "Maximize" (1270,206 48x48)
  btn-close-d1a2 "Close" (1318,206 48x48)

Slugy zobrazené ve výstupu (např btn-minimize-d1a0. ) lze použít přímo s jinými příkazy:

winapp ui invoke btn-minimize-d1a0 -a notepad

get-property

Čtení hodnot vlastností z elementu Zahrnuje stav specifický pro vzor (ToggleState, Value, IsSelected atd.).

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

screenshot

Zachyťte okno nebo prvek jako PNG. Pokud existuje více oken (např. dialogové okno aplikace + otevřené), jsou složené do jednoho PNG s každým oknem stehovanými.

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)

Když jsou otevřená dialogová okna nebo automaticky otevíraná okna, jsou všechna okna složená do jednoho formátu PNG, abyste viděli úplný stav uživatelského rozhraní v jednom obrázku.

Použijte --capture-screen , když potřebujete zachytit místní nabídky, rozevírací seznamy, kontextové rámečky nebo překryvné popisky. V --capture-screen režimu (a při opakování po zjištění prázdného rámce) se cílové okno nejprve přenese do popředí. Normální zachytávání oken okno nepřesune.

volat

Aktivujte prvek prostřednictvím kódu programu (kliknutím na tlačítko, přepínací políčko, rozbalte pole se seznamem).

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

Vzory Tries v pořadí: InvokePattern → TogglePattern → SelectionItemPattern → ExpandCollapsePattern.

click

Klikněte na prvek na souřadnicích obrazovky pomocí simulace myši. Tuto možnost použijte pro ovládací prvky, které nepodporují InvokePattern (například záhlaví sloupců, položky seznamu).

winapp ui click btn-column1-a3f2 -a myapp              # single click by slug
winapp ui click "Column1" -a myapp                      # single click by text search
winapp ui click btn-column1-a3f2 -a myapp --double      # double-click
winapp ui click btn-column1-a3f2 -a myapp --right       # right-click

set-value

Nastavte hodnotu u upravitelného prvku (text pro TextBox/ComboBox, číslo posuvníku).

winapp ui set-value txt-textbox-a4b1 "Hello world" -a notepad
winapp ui set-value sld-volume-b2c3 75 -a myapp

get-value

Přečtěte si aktuální hodnotu z elementu. Používá inteligentní záložní řetězec: TextPattern (RichEditBox, Document) → ValuePattern (TextBox, Slider) → SelectionPattern (ComboBox, RadioButton, TabView) → Název (popisky).

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

Přesunutí fokusu klávesnice na prvek

winapp ui focus txt-textbox-a4b1 -a notepad

scroll-into-view

Posuňte prvek do viditelné oblasti.

winapp ui scroll-into-view itm-targetitem-c3d4 -a myapp

čekání

Počkejte, až se prvek zobrazí, zmizí nebo bude mít hodnotu, která dosáhne cíle.

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

Posunout

Posuňte prvek kontejneru. Vyhledejte posuvné kontejnery search scroll – hledejte [scroll:v] (svislé) nebo [scroll:h] (vodorovné) značky.

# Find which elements are scrollable and in which direction
winapp ui search scroll -a myapp
#   pn-scrollview-bfef Pane "scrollView" [scroll:v] (main content, vertical)
#   pn-scrollviewer-bfb1 Pane "scrollViewer" [scroll:h] (horizontal list)

# Scroll the main content down
winapp ui scroll pn-scrollview-bfef --direction down -a myapp

# Jump to top/bottom
winapp ui scroll pn-scrollview-bfef --to bottom -a myapp

# If you target an element that's not scrollable, scroll walks up to find the nearest scrollable parent
winapp ui scroll itm-someitem-a1b2 --direction down -a myapp

get-focused

Umožňuje zobrazit prvek, který má aktuálně fokus klávesnice.

winapp ui get-focused -a myapp

list-windows

Zobrazí seznam všech viditelných oken pro aplikaci, včetně automaticky otevíraných oken a dialogových oken.

winapp ui list-windows -a imageresizer
winapp ui list-windows -a Terminal
winapp ui list-windows                                      # all windows (no filter)

Podpora architektury

.NET Framework Zkontrolovat hledání volat set-value screenshot
WPF (Windows Presentation Foundation) ✅ Celý strom ✅ Všechny vlastnosti ✅ Všechny vzory
Formuláře WinForms
Win32
WinUI 3
Elektron ⚠️ Chromium strom ⚠️ Omezené ⚠️ Liší se ⚠️ Liší se
Flutter ⚠️ Základní ⚠️ Základní ❌ Minimální

Troubleshooting

Error Příčina Solution
"Nenalezena žádná spuštěná aplikace" Neshoda názvů nebo spuštění aplikace Kontrola názvu procesu nebo použití PID
"Shoda s více okny" Nejednoznačná -a hodnota Použití -w <HWND> z uvedených možností
"má více oken" Proces má více oken. Slouží -w <HWND> k cílení na konkrétní.
"Selektor odpovídá N prvkům" Nejednoznačný starší selektor Použití slugů z inspect výstupu nebo připojení [1][0]ke starším selektorům
"Prvek mohl být změněn" Hodnota hash Slug neodpovídá aktuálnímu prvku Opětovné spuštění inspect nebo search získání čerstvých slugů
"nepodporuje žádný vzor vyvolání" Prvek nelze vyvolat. Použití inspect elementu k vyhledání vyvolání podřízeného objektu
"Nenašlo se žádné okno UIA" UiA nemůže zobrazit proces Použijte list-windows k nalezení HWND a pak -w
"Okno má nulovou velikost" Minimalizované okno Aplikace se automaticky obnoví.
Místní nabídka nebo rozevírací seznam, který není na snímku obrazovky PrintWindow nezachytává překryvy Použít --capture-screen příznak

Běžné vzory

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

Vyhledání textu a vyvolání jeho nadřazeného objektu

# 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

Zrušit nejednoznačnost duplicitních prvků

winapp ui search '#Image' -a myapp; winapp ui invoke itm-image-a2b3 -a myapp

Snímek obrazovky s překryvnými překryvnými okny

winapp ui set-value txt-searchbox-e5f6 "query" -a myapp; winapp ui screenshot -a myapp --capture-screen
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

Zjišťování, kliknutí a ověření

winapp ui inspect -a myapp --interactive; winapp ui invoke btn-submit-7a90 -a myapp; winapp ui screenshot -a myapp

Interakce s dialogovým oknem Soubor

Dialogy otevření/uložení souborů jsou standardní Windows dialogy s podporou 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>

Slouží inspect -w <dialog-hwnd> --interactive ke zjištění skutečných slugů pro konkrétní dialogové okno.

Proč ; řetězení (ne &&)

Operátor PowerShellu && může ukotvit, když nativní rozhraní příkazového řádku zapisuje do stderru nebo používá řídicí sekvence ANSI. Používejte ; místo toho – spouští každý příkaz bezpodmínečně a vyhne se tomuto vzájemnému zablokování. To je také lepší pro pracovní postupy agenta: Obvykle chcete, aby se snímek obrazovky spustil i v případě, že vyvolání mělo nenulové ukončení.

Vzory testování CI

Pro orientační testy a ověřování uživatelského rozhraní použijte příkazy winapp ui v kanálech CI (GitHub Actions, Azure DevOps). wait-for s kontrolním výrazem --property a --value funguje jako kontrolní výraz – vrátí ukončovací kód 1 při vypršení časového limitu a automaticky selhává krok CI.

Spuštění a testování v 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

Assert – stav elementu s wait-for

wait-for --value se dotazuje, dokud hodnota prvku neodpovídá očekávanému řetězci, a to pomocí stejného inteligentního náhradního objektu jako get-value (TextPattern → ValuePattern → SelectionPattern → Name). Vrátí ukončovací kód 0 při shody, ukončete kód 1 při vypršení časového limitu – což z něj dělá kontrolní výraz kompatibilní s CI. Slouží --property ke kontrole konkrétní vlastnosti UIA.

# 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 s výstupem JSON

Použití --json s PowerShellem nebo jq pro složitější kontrolní výrazy:

Ukončovací kontrakt kódu pro search a wait-for v --json režimu: pokud žádný prvek neodpovídá (search) nebo vypršení časového limitu čekání (wait-for), příkaz zapíše plně parsovatelnou obálku výsledku do stdout ({ "matchCount": 0, ... } nebo { "found": false, "timedOut": true, ... }) a vrátí ukončovací kód 1. Stderr je v --json režimu prázdný (výstup protokolovacího modulu je potlačen). Větvení na obálce polí nebo na $LASTEXITCODE, v závislosti na tom, která je ergonomickější.

# 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)" }

Příklad úplného orientačního testu

# 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