Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Sprawdzanie i interakcja z uruchamianiem aplikacji Windows z poziomu wiersza polecenia. Używane przez agentów sztucznej inteligencji i deweloperów do testowania, debugowania i automatyzacji interfejsu użytkownika.
Przegląd
winapp ui udostępnia polecenia do inspekcji i interakcji z interfejsami użytkownika aplikacji Windows.
Używa Windows automatyzacja interfejsu użytkownika (UIA). Współpracuje z dowolną aplikacją Windows — WPF, WinForms, Win32, Electron i WinUI 3.
Większość poleceń napędza aplikację za pomocą wzorców interfejsu użytkownika (bez iniekcji danych wejściowych). Wyjątki wprowadzają rzeczywiste dane wejściowe: ui click/ui hoverui drag/używaj symulacji myszy,/ui touchui pen syntetyzują dane wejściowe dotyku i pióra/rysika oraz ui send-keys syntetyzują dane wejściowe klawiatury — w przypadku kontrolek i scenariuszy, których wzorce UIA nie mogą prowadzić.
Important
Wymaganie dotyczące pulpitu interakcyjnego (czasowniki iniekcji danych wejściowych).click, hover, dragtouch, pen, scroll --wheeli send-keys --via send-input syntetyzują dane wejściowe na poziomie systemu operacyjnego, więc potrzebują odblokowanego, interaktywnego pulpitu z oknem docelowym na pierwszym planie. Na zablokowanej stacji roboczej lub bezpiecznym pulpicie (LogonUI/UAC) nie mogą wstrzyknąć i szybko zakończyć się niepowodzeniem no_interactive_desktop (różni się od podniesienia uprawnień/foreground_not_target przypadków).
touch
/
penponadto odrzucanie, gdy okno nie zostanie rozpoznane (no_target); współrzędna poza oknem docelowym jest ostrzeżeniem niekrytycznym (wpis w --jsontrybie tekstowym lub wierszem ostrzegawczym) i iniekcja jest nadal kontynuowana — warnings[] zgodnie z czasownikami myszy. Wszystkie inne — inspect, , search, get-valueinvokeget-propertyset-valuescroll --direction/--towait-forscreenshot — napędza aplikację za pomocą wzorców interfejsu użytkownika i są przyjazne dla sesji bezgłowych/zablokowanych. Preferuj czasowniki wzorca UIA w ciągłej integracji; zarezerwować czasowniki iniekcji dla scenariuszy, które naprawdę potrzebują rzeczywistych danych wejściowych. Przed wstrzyknięciem czasowniki gestu również ponownie rozpoznają element docelowy i odmówić, target_moved jeśli nadal animuje/przenosi się, zamiast lądować dane wejściowe w pustym miejscu.
Szybki start
# Connect to any app and see its UI tree
winapp ui inspect -a notepad
# Find specific elements
winapp ui search Button -a notepad
# Activate an element
winapp ui invoke Close -a notepad
# Take a screenshot
winapp ui screenshot -a notepad
Określanie wartości docelowej aplikacji
Według nazwy 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
Według tytułu okna
winapp ui inspect -a "LICENSE - Notepad"
winapp ui inspect -a "Fix WinApp" # partial title match
Według identyfikatora PID
winapp ui inspect -a 12345
Przez HWND (stabilny — przetrwa zmiany tabulatora/tytułu)
# 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
Służy -a do odnajdywania w -w celu uzyskania stabilnego określania wartości docelowej. Gdy -a pasuje do wielu okien, polecenie wyświetla je z HWNDs, które chcesz wybrać.
Selektory
Elementy docelowe przy użyciu selektora wyświetlanego w [brackets] danych wyjściowych inspekcji/wyszukiwania.
Istnieją trzy typy selektorów:
| Selector | Znaczenie | Example |
|---|---|---|
MinimizeButton |
AutomationId (wyświetlany, gdy unikatowy — stabilny, preferowany) | winapp ui invoke MinimizeButton -a myapp |
btn-close-d1a0 |
Slug semantyczny (pokazany, gdy nie ma unikatowego identyfikatora AutomationId) | winapp ui invoke btn-close-d1a0 -a myapp |
Submit |
Wyszukiwanie w postaci zwykłego tekstu względem parametru Name/AutomationId (podciąg bez uwzględniania wielkości liter) | winapp ui invoke Submit -a myapp |
Selektory AutomationId to identyfikatory zestawu deweloperów (AutomationProperties.AutomationId w języku XAML).
Gdy identyfikator AutomationId jest unikatowy w całym drzewie interfejsu inspect użytkownika i search wyświetla go bezpośrednio jako selektor — te zmiany układu przetrwania, lokalizacja i restrukturyzacja drzewa.
Selektory Slug (np. ) są generowane, btn-close-d1a0gdy nie istnieje unikatowy identyfikator AutomationId.
Format: prefix-name-hash. Skrót weryfikuje tożsamość elementu, ale może przestarzał po zmianie interfejsu użytkownika.
Sprawdzanie formatu danych wyjściowych
Polecenie inspect wyświetla drzewo elementów z kolorowymi danymi wyjściowymi (selektor w cyjanku, nazwa na zielono, metadane w kolorze szarym):
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
Pierwszym wyrazem w każdym wierszu jest selektor — użyj go z innymi ui poleceniami.
Gdy element ma unikatowy identyfikator AutomationId, jest używany bezpośrednio (np. TabView, NewTabButton).
Jeśli nie istnieje unikatowy identyfikator AutomationId, jest używany wygenerowany ślimak (np. tab-newtab-5f5b).
Slugi semantyczne
Slugi używają formatu: prefix-normalizedname-hash gdzie:
- prefiks — 3-literowy skrót typu (btn, txt, chk, cmb, itm, tab, img, lbl, pn, win, grp, lnk, mnu itp.)
- normalizedname — małe litery alfanumeryczne z identyfikatora AutomationId (preferowane) lub nazwa, maksymalnie 15 znaków
- hash — skrót 4-znakowy skrót szesnastkowy identyfikatora RuntimeId elementu (weryfikuje tożsamość elementu)
Slugi są bezpieczne za pomocą powłoki (bez znaków specjalnych), unikatowe i mogą być używane bezpośrednio jako argumenty. Skrót zapewnia wykrywanie nieaktualności — jeśli element został zastąpiony, otrzymasz: "Element mógł ulec zmianie. Uruchom ponownie inspekcję".
Elementy bez nazwy lub AutomationId pokazują tylko prefiks + skrót (np. pn-c8a3).
Uściślanie wielu dopasowań
Slugi z inspect/search danych wyjściowych są unikatowe, ale mogą zmieniać się między zmianami układu — używają ich w zwykłych nazwach typów lub tekście, gdy wiele dopasowań. Gdy selektor jest niejednoznaczny, interfejs wiersza polecenia drukuje wszystkie dopasowania ze swoimi ślimakami, aby można było wybrać właściwy i ponownie uruchomić z tym ślimakiem.
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
Wyszukiwanie zwykłego tekstu
Użyj zwykłego tekstu, aby wyszukać elementy — nie jest wymagana żadna specjalna składnia:
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
Gdy wyszukiwanie tekstu pasuje do wielu elementów (np. SettingsExpander, gdzie grupa, przycisk i tekst mają taką samą nazwę), interfejs wiersza polecenia automatycznie wybiera jedyny element wywołujący. Jeśli wiele jest wywoływanych, wyświetla listę wszystkich dopasowań z ślimakami.
W przypadku wyników wyszukiwania niepodwoływalnych (np. textblock wewnątrz przycisku) wyszukiwanie automatycznie wyświetla najbliższy nadrzędny element — element nadrzędny, którego można użyć z elementem invoke.
Działa to dla wszystkich selektorów wyszukiwania:
lbl-savechanges-a1b2 "Save changes" (120,40 80x20)
^ invoke via: btn-save-c3d4 "Save"
Selektor powierzchniowy może być używany bezpośrednio:
winapp ui invoke btn-save-c3d4 -a myapp # invoke the parent Button
Komendy
stan
Połącz się z aplikacją i pokaż informacje o połączeniu.
winapp ui status -a notepad
winapp ui status -a notepad --json
Sprawdzić
Wyświetl drzewo elementów interfejsu użytkownika. Dane wyjściowe pokazują semantycznie slugi z wcięciem 2-spacji dla 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
Przykładowe dane wyjściowe (wartość domyślna):
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)
Przykładowe dane wyjściowe (--interactive — tylko elementy, lista płaska):
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)
Elementy mogą pokazywać następujące znaczniki stanu:
-
[on]/[off]/[indeterminate]— stan przełącznika/pola wyboru -
[collapsed]/[expanded]— stan rozwijania/zwijania drzew, pól kombi, elementów menu -
[scroll:v]/[scroll:h]/[scroll:vh]— kontener przewijany (pionowy, poziomy lub oba) -
[offscreen]— element nie jest widoczny na ekranie -
[disabled]— element nie jest włączony -
value="..."— bieżąca zawartość tekstowa elementów edytowalnych (gdy różni się od nazwy)
wyszukać
Znajdowanie elementów pasujących do selektora. Dane wyjściowe pokazują semantycznie slugi:
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
Przykładowy wynik:
btn-minimize-d1a0 "Minimize" (1222,206 48x48)
btn-maximize-e2b1 "Maximize" (1270,206 48x48)
btn-close-d1a2 "Close" (1318,206 48x48)
Slugi wyświetlane w danych wyjściowych (np. btn-minimize-d1a0) mogą być używane bezpośrednio z innymi poleceniami:
winapp ui invoke btn-minimize-d1a0 -a notepad
get-property
Odczytywanie wartości właściwości z elementu. Obejmuje stan specyficzny dla wzorca (ToggleState, Value, IsSelected itp.).
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
zrzut ekranu
Przechwyć okno lub element jako PNG. Gdy istnieje wiele okien (np. aplikacja + otwarte okno dialogowe), są one złożone w jeden plik PNG z każdym oknem zeszytymi.
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; foregrounds window)
winapp ui screenshot -a myapp --focus # bring window to foreground first, then capture (default WGC path)
Gdy okna dialogowe lub wyskakujące okienka są otwarte, wszystkie okna są złożone w jeden plik PNG, dzięki czemu można zobaczyć pełny stan interfejsu użytkownika w jednym obrazie.
Domyślna ścieżka przechwytywania używa Windows. Graphics.Capture (WGC) odczytywanie rzeczywistej powierzchni złożonej DWM — zachowanie zaokrąglonych narożników, przezroczystości i pracy nawet wtedy, gdy okno jest okludnione przez inne windows. Jeśli usługa WGC jest niedostępna (starsze Windows kompilacje), interfejs wiersza polecenia wraca do usługi PrintWindow.
Użyj --capture-screen polecenia , gdy musisz przechwytywać menu podręczne, listy rozwijane, wysuwane lub nakładki etykietek narzędzi, które nie są własnością okna docelowego.
--capture-screen odczytuje z kontrolera domeny ekranu i najpierw przenosi okno na pierwszy plan. Użyj --focus polecenia , jeśli chcesz po prostu na pierwszym planie okna bez przełączania trybów przechwytywania (np. aby upewnić się, że zrzut ekranu jest zgodny z tym, co aktualnie patrzy użytkownik).
rekord
Zarejestruj okno docelowe (lub region elementu) na wideo H.264 MP4. Ramki są przechwytywane za pośrednictwem funkcji przechwytywania grafiki Windows (z rezerwowym elementem PrintWindow/screen-DC) i kodowane przyrostowo za pomocą programu Media Foundation, więc nagrania nigdy nie buforują pełnego wideo w pamięci.
Zachowanie domyślne (--duration-sec 0): rejestruje rekordy do momentu zatrzymania. Użyj kombinacji klawiszy Ctrl+C interaktywnie lub (w przypadku programowych/ wywołujących agentów) napisz nowy wiersz do stdin lub zamknij stdin, aby zatrzymać i sfinalizować MP4 bezpiecznie. Prawidłowy, odtwarzany MP4 jest zawsze sfinalizowany na każdym łaskawym zatrzymaniu — bez uszkodzenia.
# Timed: record for 10 s at 15 fps
winapp ui record -a myapp --duration-sec 10 --fps 15 --output demo.mp4
# Unbounded (default): record until Ctrl+C, downscaled to max 1280px longest edge
winapp ui record -a myapp --max-edge 1280 --output capture.mp4
# Programmatic stop (agent/script): pipe a newline; the recorder stops and writes a valid MP4
"" | winapp ui record -a myapp --json --output capture.mp4
# Record a single element's region (fails with element_not_found if the selector doesn't match)
winapp ui record itm-chart-9f8e -a myapp --output chart.mp4
# Include screen overlays / popups (captures from screen DC; brings window to foreground)
winapp ui record -a myapp --capture-screen --duration-sec 5 --output with-popups.mp4
Opcje:
-
--duration-sec N— rekord przez N sekund. Wartość domyślna 0 = rekord do momentu zatrzymania. -
--fps N— ramki docelowe na sekundę (domyślnie 15). -
--max-edge N— Skalowanie w dół, tak aby najdłuższa krawędź wynosi najwyżej N pikseli (0 = bez skalowania w dół). -
--capture-screen— Przechwytywanie z kontrolera domeny ekranu (obejmuje nakładki/wyskakujące okienka; pierwszego planu). -
--output <path>— ścieżka mp4 danych wyjściowych. Wartość domyślna torecording-<timestamp>-<guid>.mp4w bieżącym katalogu.
Zatrzymaj mechanizmy:
- Interakcyjne: Ctrl+C (dowolna platforma).
- Programowy/agent: napisz nowy wiersz (
"") lub zamknij stdin (EOF). Zatrzymanie jest stosowane natychmiast po zakończeniu kodera (przechwycona pierwsza ramka); każdy sygnał zatrzymania, który pojawia się przed pierwszą ramką jest zatrzaśnięty i stosowany natychmiast w gotowości — nie ma okna łaski i nie ma opóźnienia zegara ściany.
Tryby przechwytywania (zgłoszone w polu JSON mode ):
-
wgc— Windows przechwytywania grafiki (ustawienie domyślne; działa, gdy okno jest okludne). -
printwindow— GDI PrintWindow (powrót, gdy usługa WGC jest niedostępna w tym systemie/sesji; uruchom ponownie polecenie ,--capture-screenaby zamiast tego użyć kontrolera domeny ekranu). -
screen— Kontroler domeny ekranu za pośrednictwem (--capture-screenobejmuje nakładki/wyskakujące okienka; przenosi okno na pierwszy plan).
Dane wyjściowe JSON (--json):
-
stdout (wynik końcowy):
{ "path", "frames", "width", "height", "fileSize", "codec": "h264", "mode", "fps", "durationSec" } -
stderr (zdarzenie liveness, emitowane po rozpoczęciu przechwytywania):
{ "event": "recording-started", "path", "fps", "durationSec" }
Zdarzenie liveness na stderr pozwala programowym wywołującym wiedzieć, że pętla przechwytywania jest aktywna bez oczekiwania na końcowy wynik. Końcowy wynik JSON w stdout jest pojedynczym czystym obiektem.
Kody błędów:
-
element_not_found— Selektor podany, ale nie znaleziono pasującego elementu; natychmiast kończy się niepowodzeniem (nie zapisano pliku częściowego). -
ambiguous_selector— Selektor zwykłego tekstu pasował do wielu elementów; użyj sluga z sugestii wyświetlanych w błędzie (lub zinspectdanych wyjściowych), aby wskazać określony element. -
invalid_arguments— Nieprawidłowa wartość opcji (np.--duration-sec -1lub> 86400).
Znane ograniczenie — wyskakujące okienka: Podczas rejestrowania określonego elementu (selektora), który znajduje się wewnątrz okna podręcznego, które renderuje się we własnym oknie najwyższego poziomu — np. okna wysuwanego WinUI/XAML, porada dydaktyczna, etykietka narzędzia lub menu (Xaml_WindowedPopupClass) — rejestrator może przechwytywać podstawowe okno główne zamiast okna podręcznego, tworząc puste lub przestarzałe ramki. Zarejestruj całe okno (pomiń selektor) lub użyj winapp ui screenshot --capture-screen w przypadku okien podręcznych. Śledzone w 646.
Programowe aktywowanie elementu (kliknij przycisk, przełącz pole wyboru, rozwiń pole kombi).
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
Próbuje wzorce w kolejności: InvokePattern → TogglePattern → SelectionItemPattern → ExpandCollapsePattern.
click
Kliknij element na jego ekranie współrzędnych przy użyciu symulacji myszy. Służy do kontrolek, które nie obsługują InvokePattern (np. nagłówki kolumn, elementy listy).
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
Podobnie jak inne czasowniki wstrzykiwania danych wejściowych,
clickprzenosi element docelowy na pierwszy plan i szybko kończy się niepowodzeniem (no_interactive_desktopna zablokowanym/bezpiecznym pulpicie,foreground_not_targetjeśli nie można przenieść fokusu) zamiast klikać nieprawidłowe okno. Usuwa również ponownie element tuż przed przyciskiem w dół: po ustawieniu kursora wykonuje jedno końcowe sprawdzanie położenia, więc stale przesuwający się/animujący element docelowy kończy się niepowodzeniemtarget_movedzamiast raportowania powodzenia po kliknięciu wylądował na pustym miejscu — zgłoszony sukces oznacza, że cel był nadal w miejscu, gdy przycisk spadł.
przeciągnąć
Naciśnij przycisk myszy w jednym momencie, przejdź do innego, a następnie zwolnij element za drag <from> <to>pomocą polecenia , gdzie każdy punkt końcowy jest selektorem elementów (przeciąga się z/do środka elementu) lub współrzędnych x,yekranu dokładnie zgodnie z raportem.winapp ui inspect Mieszaj i dopasuj swobodnie (selektor→selector, selektor→koordy, współordy→koordy).
Używa z SendInput ruchami pośrednimi, aby aplikacja widziała realistyczny strumień komunikatów WM_MOUSEMOVE . Służy do zmieniania kolejności/zmieniania rozmiaru uchwytów, suwaków, rysunku kanwy i przeciągania i upuszczania.
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
Opcje:
-
--right— przeciągnij prawym przyciskiem myszy zamiast lewego przycisku. -
--hold-ms <ms>— Przytrzymaj przycisk w dół na początku przed przeniesieniem (ustawienie domyślne: 0). Z<from> == <to>(bez ruchu) wykonuje gest naciśnięcia i trzymania / długiego naciśnięcia . -
--dwell-ms <ms>— Mieszkaj w miejscu docelowym po przeniesieniu, przed zwolnieniem (wartość domyślna: 0). Pozwala upuścić elementy docelowe /scalać nakładki , które uzbrajają się z trwałego aktywowania (a nie natychmiast pojawia się kursor) zatrzasnąć przed przyciskiem.
Słupki
x,ysą współrzędnymi ekranu w tym samym raporcie spacjiwinapp ui inspect/search, a selektor rozpoznaje środek elementu — najpierw sprawdź punkty, aby wybrać punkty.
Podobnie jak
send-keys --via send-input,dragwstrzykuje współrzędne systemu operacyjnego na ekranie po doprowadzeniu celu na pierwszy plan. Jeśli nie można skierować fokusu do miejsca docelowego (np. zapobiegania kradzieży fokusu z procesu w tle), polecenie kończy się niepowodzeniem (foreground_not_target) zamiast przeciągania na niewłaściwe okno — fokus lub kliknij okno jako pierwsze. Na zablokowanym/bezpiecznym pulpicie kończy się niepowodzeniem z programemno_interactive_desktop. Każdy punkt końcowy elementu jest rozpoznawany ponownie bezpośrednio przed przeciągnięciem; Jeśli nadal przenosi się/zmienia rozmiar (animowanie elementu docelowego), polecenie kończy się niepowodzeniemtarget_movedzamiast przeciągania do nieaktywnego punktu.x,y(Nie można ponownie zweryfikować bez punktów końcowych, więc są używane as-is).
Dotyk
Wstrzykiwanie syntetycznych gestów dotykowych przy użyciu interfejsu API wstrzykiwania wskaźnika Windows. Kotwica kontaktu jest selektorem elementów (używa środka elementu) lub jawną współrzędną x,yekranu za pośrednictwem --at (te same raporty spacjiwinapp ui inspect). Użyj go do interakcji naciśnięcia/naciśnięcia i gestów wielodotyku, których symulacja myszy nie może wyrazić.
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)
Opcje:
-
--gesture <g>—tap(ustawienie domyślne),double-tap,long-press,swipe,pinch.stretch -
--at <x,y>— jawny punkt początkowy (współrzędne ekranu). Domyślnie jest to środek elementu selektora. -
--to-point <x,y>— Punkt końcowy dla elementuswipe. Ma pierwszeństwo przed--direction. -
--direction <right|left|up|down>— Kierunek przesunięcia (ustawienie domyślne:right). W połączeniu z elementem--distancew celu obliczenia punktu końcowego, gdy--to-pointnie zostanie podany. -
--distance <px>— Rozrzuć palcem napinch/stretchodległość w pikselach lub machnięcia. -
--hold-ms <ms>— Przytrzymaj kontakty w dół przed zniesieniem (czas wstrzymania długiego naciśnięcia; wartość domyślna to 500 ms,long-pressjeśli nie jest ustawiona). -
--duration-ms <ms>— Czas ślizgu dla ruchliwych gestów (szybkie przesunięcie/szczypta/rozciągnięcie; wartość domyślna 300). -
--fingers <n>— liczba kontaktów (1–10; wartość domyślna 1).pinch/stretchzawsze używaj 2.
Bezpieczeństwo iniekcji.
touchodmawia wstrzyknięcia, chyba że uchwyt okna docelowego niezerowego zostanie rozwiązany i to okno zawiera pierwszy plan — kończy się niepowodzeniemno_target, gdy nie można rozpoznać okna,foreground_not_targetjeśli nie można przenieść fokusu lubno_interactive_desktopna zablokowanym/bezpiecznym pulpicie. Każda współrzędna (środek elementu, jawne--at/--to-pointi wygenerowane punkty waypoints) jest sprawdzana względem prostokąta okna docelowego. Punkt poza oknem jest przedstawiany jako ostrzeżenie niekrytyczne (warnings[]wpis w--jsonlub wiersz ostrzeżenia w trybie tekstowym) i iniekcja nadal następuje — dopasowanie czasowników myszy (drag/scrollclick/hover/), które również wprowadza współrzędne poza oknem.--fingerspowyższe 10 jest odrzucane z góry.Uwaga sprzętowa. Funkcja Touch preferuje nowoczesne urządzenie wskaźnika syntetycznego (
CreateSyntheticPointerDevice(PT_TOUCH)) i wraca do starszegoInitializeTouchInjection/InjectTouchInputinterfejsu API. Jeśli iniekcja jest nieobsługiwana na bieżącym urządzeniu/sesji, polecenie wyświetla rzeczywisty kod błędu Win32 (np. "nieobsługiwany") zamiast zgłaszać fałszywe powodzenie — traktuj wyjście niezerowe jako "nie dostarczono dotyku".Remote Desktop/sesje maszyn wirtualnych. W przypadku Remote Desktop (RDP) lub niektórych sesji maszyny wirtualnej system operacyjny może zaakceptować syntetyczne dotknięcie (wyjście 0) bez dotarcia do aplikacji docelowej. Po wykryciu
touchsesji zdalnej dołącza ostrzeżenie dotyczące niepewności dostarczania —warnings[]wpis w--jsonsystemie lub wiersz ostrzeżenia w trybie tekstowym. / ✅exit 0 oznacza następnie wywołanie iniekcji powiodło się, a nie , że aplikacja otrzymała dane wejściowe; potwierdź efektui screenshot/ui inspect, gdy ma znaczenie.
długopis
Wstrzykiwanie syntetycznych danych wejściowych pióra/rysika — naciśnięcia i pociągnięcia atramentu — przy użyciu interfejsu API Windows syntetycznego wskaźnika (CreateSyntheticPointerDevice(PT_PEN); Windows 10 1809+). Wyceluj w środek elementu, punkt jawny --at lub pełny --path pociągnięcie pisma odk.
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
Opcje:
-
--at <x,y>— Punkt styku pióra (współrzędne ekranu). Domyślnie jest to środek elementu selektora. Ignorowane, gdy--pathzostanie podane. -
--path "<x,y x,y …>"— Ścieżka pociągnięć pisma od pisma od ręcznego jako pary rozdzielanex,yodstępami (ścieżka jednopunktowa jest naciśnięciem). -
--pressure <0.0–1.0>— Ciśnienie pióra (domyślnie 0,5). -
--tilt-x <deg>/--tilt-y <deg>— Kąty pochylenia pióra, od −90 do 90 (domyślnie 0). -
--eraser— Użyj końca gumki pióra zamiast końcówki. -
--duration-ms <ms>— Łączny czas podróży pociągnięcia w milisekundach dystrybuowany jako interpolowane ramki AKTUALIZACJI w ścieżce (wartość domyślna: ~10 ms w punkcie drogi). Użyj tej funkcji, aby kontrolować, jak szybko pióro wyraźnie porusza się od początku do końca.
Bezpieczeństwo iniekcji. Podobnie jak
touch,penodmawia wstrzykiwania bez zera, pierwszego planu okna docelowego (no_target/foreground_not_target/no_interactive_desktop) i sprawdza każdy punkt pisma odręcznego względem prostokąta okna docelowego, wyświetlając dowolną współrzędną poza oknem jako ostrzeżenie niekrytyczne (warnings[]w--json, lub w wierszu ostrzeżenia w trybie tekstowym) podczas wstrzykiwania — zgodne z czasownikami myszy. Nieprawidłowe--pressure(poza 0.0–1.0) lub przechylenie (na zewnątrz ±90°) są odrzucane z góry.Remote Desktop/sesje maszyn wirtualnych. Routing piórem jest szczególnie zawodny w przypadku Remote Desktop: wywołanie iniekcji może zgłosić powodzenie (wyjście 0), podczas gdy żadne dane wejściowe pióra nie docierają do aplikacji. Po wykryciu
pensesji zdalnej dołącza ostrzeżenie o niepewności dostarczania (warnings[]w systemie lub wierszu ostrzeżenia w--jsontrybie tekstowym), dzięki czemu ✅ potwierdzenie dostarczenia nie jest mylące. Zweryfikuj przepływy zależne od pióra na lokalnym, interaktywnym pulpicie.
wskaźnik aktywowania
Przenieś wskaźnik myszy na środek elementu, aby wyzwolić efekty aktywowania (etykietki narzędzi, wysuwane, stany wizualne). Używa SendInput do realistycznego ruchu myszy z małym przełącznikiem, a następnie czeka na konfigurowalny czas zamieszkania.
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 hover btn-info-a1b2 -a myapp; winapp ui screenshot -a myapp --capture-screen # hover then capture tooltip
Opcje:
-
--dwell-time <ms>— czas w milisekundach oczekiwania po umieszczeniu wskaźnika myszy na wyświetlaniu efektów (wartość domyślna: 800, zakres: 0–10000)
send-keys
Wysyłanie syntetycznych danych wejściowych klawiatury — odpowiednik klawiatury do click. UIA nie ma wzorca iniekcji klawiatury, więc to spada do warstwy Win32. Służy do nawigacji za pomocą klawiatury (strzałek, klawiszy Tab, Enter, Esc), skrótów (ctrl+c, alt+f4), i wpisywania w kontrolkach, które wymagają zdarzeń naciśnięć klawiszy, a nie set-valuedo zapisu niepodzielnego.
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
Gramatyka klucza (tokeny rozdzielane odstępami, cudzysłów ciągi wielo tokenów):
-
Nazwane klucze —
enterreturn/,esc.capslockprintscreentab/escapespacebackspacedelete/delinserthomeendpageup/pguppagedown/pgdnup/down/left/rightf1f16apps -
Sekwencje — wiele tokenów jest naciskanych w kolejności:
down down enter. -
Kombi modyfikatora —
ctrl,shiftwinaltsprzężone z+:ctrl+shift+t, .alt+f4 -
Tekst literału — każdy token, który nie jest znanym kluczem, jest wpisany znakiem według znaku:
hello. Sąsiadujące wyrazy literału zachowują odstęp między nimi, więc fraza w cudzysłowie, taka jak"Hello world", jest wpisywana dosłownie (spacja jest zachowywana); literał, który zawiera tylko+tekstC++luba+bjest wpisywany jako tekst, a nie analizowany jako kombi. -
Jawna ucieczka literału — prefiks tokenu z
text=, aby wpisać go dosłownie, nawet jeśli zderzy się z nazwą klucza lub modyfikatora:text=enterwpisz wyraz "enter" zamiast naciskać klawisz Enter itext=ctrl+awpisz ciąg literału. Odzwierciedla ucieczkęvk=; unikniętą wartość nadal łączą się z sąsiednimi wyrazami literału (text=down low→ "w dół niski"). Ponieważ tokeny są rozdzielone odstępami (a sąsiadujące literały ponownie łączą się z jedną spacjątext=), użyj ukośników odwrotnych wewnątrz wartości , aby wpisać odstępy, które nie przetrwałyby w przeciwnym razie:\s→ spacji, → tabulatora,\t→ nowego wiersza,\n→ nowego wiersza,\r\\→ ukośnik literału.\n,\ri\r\nkażda wstawia pojedynczy podział wiersza (Enter /VK_RETURN), tak itext=line1\nline2text=line1\r\nline2wpisz jeden nowy wiersz. Dlategotext=a\s\sbwpisze "a b" (podwójna spacja) itext=\shiutrzymuje wiodącą przestrzeń. Nierozpoznana ucieczka (np.\x) jest pozostawiona dosłownie. -
Literał całego argumentu (
--verbatim) — gdy cały ładunek jest tekstem literału, należy przekazać--verbatimzamiast uciekać przed każdym tokenem za pomocątext=polecenia . Typuje cały argument kluczy dokładnie tak, jak podane — bez nazwanego klucza/kombi/vk=/text=interpretacji — i, w przeciwieństwie do normalnej ścieżki, zachowuje dokładne białe znaki wewnętrzne (bez zwijania\s) bez konieczności . Dlategosend-keys "down down enter" --verbatimwpisze wyrazy isend-keys "a b" --verbatimutrzymuje podwójną spację. Ucieczki ukośnika odwrotnego nie są dekodowane w--verbatimtrybie (\sznak jest wpisywany jako ukośnik odwrotny i znak "s"); należy użyćtext=tokenu, gdy potrzebujesz znaku kontrolki z znakiem ucieczki. -
Nieprzetworzone klucze wirtualne —
vk=0xNN(szesnastkowe) lubvk=NN(dziesiętne) dla kluczy bez przyjaznej nazwy.
Opcje:
-
--target <selector>— Fokusuj ten element (za pośrednictwem interfejsu użytkownika) przed wysłaniem kluczy. Bez niego klucze przechodzą do aktualnie ukierunkowanego elementu aplikacji. -
--verbatim— Wpisz cały argument keys jako tekst literału (bez klucza/kombi/vk=/text=analizowania) i zachowaj dokładne odstępy. Cała forma argumentu ucieczki na tokentext=. -
--via <transport>—post-message(domyślnie) wpisyWM_CHARWM_KEYDOWN/WM_KEYUP/w kolejce okna docelowego. Jest przeznaczony dla HWND i pomija interfejs użytkownika (działa na różnych poziomach integralności).send-inputwstrzykuje system operacyjny przez iSendInputprzechodzi do okna pierwszego planu.
Wybieranie transportu/znanych limitów:
-
post-messagejest wartością domyślną, ponieważ pomija interfejs użytkownika i nie zależy od pierwszego planu okna. Limity: nie może wyzwalać globalnych kluczy dostępu zarejestrowanych za pośrednictwemWH_KEYBOARD_LLpunktów zaczepienia niskiego poziomu (te naciśnięcia wejścia nadrzędnego dowolnego kolejki okien) i aplikacje odczytujące stan klucza pierwotnego za pośrednictwemGetAsyncKeyStatemogą nie obserwować zatrzymanych modyfikatorów. Automatycznie rozpoznaje i publikuje w docelowym oknie podrzędnym wątku (za pośrednictwemGetGUIThreadInfo) po pierwszym planie, dlatego klasyczne aplikacje Win32/WinForms, których kontrolki są oddzielnymi oknami podrzędnymi, odbierają klucze bez ręcznego określania wartości docelowej kontrolki. Aplikacje WinUI 3 / UWP mają bez okien kontrolki XAML bez podrzędnego HWND, więc wysłanaWM_CHAR/WM_KEYDOWNnie ma nic do lądowania i jest porzucona — po komunikacie nie można ich napędzać (polecenie ostrzega i kończy 0); użyj polecenia--via send-input. (WPF okna to single-HWND i klucze trasy do wewnętrznie ukierunkowanego elementu, więc post-message działa tam.) -
send-inputTworzy w pełni rzeczywiste dane wejściowe (modyfikatory widoczne dlaGetAsyncKeyState, uruchamia punkty zaczepienia niskiego poziomu), ale przechodzi do dowolnego okna na pierwszym planie i jest blokowany przez interfejs UIPI podczas wstrzykiwania z procesu z podwyższonym poziomem uprawnień do celu niższej integralności (AppContainer/AppX). Jeślisend-inputzgłasza błąd, element docelowy jest prawdopodobnie podwyższony lub aplikacja AppX — użyj poleceniapost-messagelub uruchom interfejs wiersza polecenia na zgodnym poziomie integralności. Jako ochroniarz sprawdza,send-inputczy okno docelowe znajduje się na pierwszym planie bezpośrednio przed wstrzyknięciem i niepowodzeniem (foreground_not_target), zamiast wpisywać w niewłaściwym oknie , jeśli fokus nie może zostać przeniesiony do niego — fokus lub kliknij okno jako pierwsze. Zamiast tego na zablokowanym lub bezpiecznym pulpicie kończy się niepowodzeniemno_interactive_desktop(nie istnieje okno pierwszego planu do wstrzykiwania) — odblokuj sesję lub użyj czasownika UIA-pattern (set-value,invoke). -
Kombi zarezerwowane systemu (
win+l,win+r,alt+f4ctrl+escalt+tabctrl+shift+escctrl+alt+delsamotnewin/printscreen, ...) działają na systemie operacyjnym/powłoce, a nie tylko na obiekcie docelowym podczas wysyłania całego systemu operacyjnego.send-inputodrzuca je domyślnie (błędy zinvalid_argumentsi wysyła nic), ponieważ wstrzykiwanie ich na poziomie systemu operacyjnego ma efekty daleko poza okno docelowe (np.win+lzablokowałoby sesję). Przekaż--allow-system-keys, aby wyrazić zgodę — umożliwia to prowadzenie globalnego klucza dostępu, takiego jak PowerToys'win+shift+vlubwin+r(globalny punkt zaczepienia niskiego poziomu obserwuje strumień wejściowy dla całego systemu operacyjnego, więc wstrzyknięte kombi go uruchamia). Wyjątki, które pozostają zablokowane nawet--allow-system-keysza pomocą polecenia :win+lblokuje stację roboczą, za pomocąLockWorkStation()której nie można rozpoznać z automatyzacji (przerywa sesje ciągłej integracji i pulpitu zdalnego) ictrl+alt+deljest sekwencją bezpiecznej uwagi (SAS), która Windows spada z wstrzykniętych danych wejściowych niezależnie od flagi — nigdy nie może obowiązywać, więc błędy (invalid_argumentswyjście 1) zamiast zgłaszać wprowadzający błąd. Inne kombi (alt+f4,ctrl+shift+esc, ,win+r...) stają się dozwolone za pomocą flagi — uważaj, wywołując. Alternatywnie, aby dostarczyć kombi systemowej do określonego okna, użyj--via post-messagepolecenia , który jest zakresem okna i nie ma to wpływu (wysłanawin+ljest nieszkodliwa, choć wysłanaalt+f4nadal zamyka okno docelowe).
Zdarzenia na naciśnięciu klawiszy (KeyDown/ TextChanged):
-
Nazwane klucze i kombi modyfikatora (
down,enter,ctrl+shift+t,vk=0xNN) uruchamiają rzeczywisteKeyDown(iKeyUp) w obu transportach — są dostarczane jako dyskretneWM_KEYDOWN/WM_KEYUP(lubSendInputzdarzenia klucza wirtualnego). -
Tekst wpisany literał (
hello) różni się transportem:-
--via send-inputmapuje każdy znak na jego wirtualny klawisz (plus Shift) na aktywny układ klawiatury, więc element docelowy widzi prawdziwyKeyDownz poprawnym kluczem wirtualnym , a następnie skomponowanyWM_CHARprzez system operacyjny (podnoszącyTextChanged) — tj. jeden pełny naciśnięty klawisz na znak. Znaki nieosiągalne w bieżącym układzie (lub wymagając klawiszy Ctrl/AltGr) wracają do pakietu Unicode, więc dokładny znak nadal ląduje. Użyjsend-inputpolecenia , jeśli potrzebujesz wierności na naciśnięciuKeyDownklawiszy (np. jazdy winUI 3 / WPFTextBox, którego klucz obsługi jest wyłączonyKeyDown). W przypadku normalnego (innego niż podwyższony poziom) hosta testowego WinUI 3 przełącz okno na pierwszy plan (winapp ui focus/ kliknięcie go), ponieważsend-inputjest ono przeznaczone dla okna pierwszego planu. -
--via post-messagepublikuje pojedynczy znakWM_CHAR( nie publikujeWM_KEYDOWN/WM_KEYUPtekstu wpisanego — są one zarezerwowane dla nazwanych kluczy/kombi), które nie zgłaszają znaku na znakKeyDown. Automatycznie retargets do ukierunkowanej kontrolki podrzędnej okna, więc klasyczne kontrolki Edycji Win32/WinFormsWM_CHARwylądować tekst (podnoszenieTextChanged). Zastrzeżeniem: Aplikacje WinUI 3/ UWP/ XAML (podstawowy element docelowy aplikacji WinApp) mają kontrolki bez okien ignorowaneWM_CHAR/WM_KEYDOWN— więc ani tekst literału , ani nazwane klucze (Enter, cyfry, ...) nie docierają do nich, mimo że polecenie zgłasza sukces. Emituje ostrzeżenie, gdy element docelowy wygląda jak XAML i nadal kończy wartość 0 (PostMessagejest uruchamiany i pomijany i nie może potwierdzić dostarczenia). Służy--via send-inputdo kierowania aplikacjami WinUI 3/UWP/WPF; zarezerwujpost-messagedla klasycznych kontrolek Win32 lub gdy są potrzebne tylko okna obejmujące poziomy integralności.
-
Dane wyjściowe JSON (--json): wynik hwnd jest skutecznym oknem, do którego zostały dostarczone klucze — w tym --via post-message celu jest to rozpoznana skoncentrowana kontrolka podrzędna, gdy polecenie retargetsuje do niego (niekoniecznie okno najwyższego poziomu-w//-a-e), dzięki czemu automatyzacja może potwierdzić dokładnie, gdzie wylądowały dane wejściowe. Gdy ten skuteczny element docelowy wygląda jak host XAML bez okien, powyższe zastrzeżenie dostarczania jest również widoczne jako warnings[] wpis (ten sam poradnik pokazany w konsoli), więc ✅ wyjście 0 nie jest mylące z potwierdzonym dostarczeniem.
set-value
Ustaw wartość elementu edytowalnego programowo (bez naciśnięć klawiszy, bez pierwszego planu aplikacji). Używa łańcucha rezerwowego:
- ValuePattern — kontrolki TextBox, ComboBox, PasswordBox i najbardziej edytowalne.
- RangeValuePattern — kontrolki liczbowe (Slider, ProgressBar), gdy wartość jest analizowana jako liczba.
-
LegacyIAccessible (
IAccessible::put_accValue) — powrót do kontrolek edycji tylko textPattern , które nie uwidaczniają elementu ValuePattern (np. pola edycji sformatowanej/Documentredagowania). Spowoduje to zamknięcie luki odczytu/zapisu, w którejget-valuemożna odczytać taką kontrolkę, aleset-valuenie może.
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
Jeśli żadna z trzech wzorców nie może ustawić wartości, set-value kończy się niepowodzeniem z wyraźnym błędem wskazującym w send-keys ostateczności.
Nie każdy bogaty edytor obsługuje zestaw programowy. Rezerwowy element LegacyIAccessible działa tylko na kontrolkach, których implementacje ułatwień dostępu — natywne kontrolki
IAccessible::put_accValueedycji Win32 i Chromium/Electron/WebView2 zwykle wykonują powierzchnie. WinUI 3RichEditBoxi WPFRichTextBoxnie obsługują programowego ustawiania wartości — zgodnie z projektem uwidaczniają zawartość automatyzacja interfejsu użytkownika jako tylko do odczytu (wzorzec tekstowy, bez wzorca wartości ustawionej), więcset-valuenie można do nich zapisywać. Użyjsend-keys(który wymaga odblokowanego, pierwszego planu pulpitu) dla tych.
get-value
Odczytaj bieżącą wartość z elementu. Używa inteligentnego łańcucha rezerwowego: TextPattern (RichEditBox, Document) → ValuePattern (TextBox, Slider) → SelectionPattern (ComboBox, RadioButton, TabView) → Name (etykiety).
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
Przenieś fokus klawiatury do elementu.
winapp ui focus txt-textbox-a4b1 -a notepad
przewiń do widoku
Przewiń element do widocznego obszaru.
winapp ui scroll-into-view itm-targetitem-c3d4 -a myapp
wait-for
Poczekaj, aż element pojawi się, zniknie lub osiągnie wartość docelową.
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
Przewiń
Przewiń element kontenera. Znajdź kontenery search scroll z możliwością przewijania — poszukaj [scroll:v] (pionowych) lub [scroll:h] (poziomych) znaczników.
# 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
Opcje:
-
--direction <up|down|left|right>— przewijanie przyrostowo za pomocą metodyScrollPattern. -
--to <top|bottom>— Przejdź do początku/końca za pomocą poleceniaScrollPattern. -
--wheel <notches>— Syntetyzowanie danych wejściowych kół myszy na środku elementu za pośrednictwemSendInput, w wycięciach kół (wcięciach):1= jeden nacięcie w górę/odchyła,-1= jeden nacięcie w dół/w kierunku,3= trzy cale w górę. (Każdy wycięcie jest WindowsWHEEL_DELTAz 120 jednostek, któreSendInputzużywają; interfejs wiersza polecenia skaluje nacięcie o 120 dla Ciebie).ScrollPatternPomija .
--direction,--toi--wheelwzajemnie się wykluczają — dokładnie jeden. Ze względu--wheelna to, że wstrzykuje dane wejściowe dla całego systemu operacyjnego na współrzędnych ekranu, element docelowy jest pierwszy na pierwszym planie i kończy się niepowodzeniem (foreground_not_target), jeśli nie można przenieść fokusu, a nie przewijania niewłaściwego okna.
uzyskiwanie fokusu
Pokaż element, który obecnie ma fokus klawiatury.
winapp ui get-focused -a myapp
list-windows
Wyświetl listę wszystkich widocznych okien dla aplikacji, w tym wyskakujących okienek i okien dialogowych. Domyślnie okna bez tytułu o zerowym rozmiarze (niewidoczne okna systemowe) są wykluczone.
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
Obsługa struktury
| Framework | Sprawdzić | wyszukać | wywołać | set-value | zrzut ekranu |
|---|---|---|---|---|---|
| WPF | ✅ Pełne drzewo | ✅ Wszystkie właściwości | ✅ Wszystkie wzorce | ✅ ¹ | ✅ |
| Windows Forms | ✅ | ✅ | ✅ | ✅ | ✅ |
| Win32 | ✅ | ✅ | ✅ | ✅ | ✅ |
| WinUI 3 | ✅ | ✅ | ✅ | ✅ ¹ | ✅ |
| Elektron | ⚠✔ Drzewo chromowe | ⚠✔ Ograniczone | ⚠✔ Różni się | ⚠✔ Różni się | ✅ |
| Flutter | ⚠✔ Podstawowa | ⚠✔ Podstawowa | ❌ Minimalne | ❌ | ✅ |
¹ set-value działa na dowolnej kontrolce, która uwidacznia wartośćPattern/RangeValuePattern, oraz kontrolki edycji tylko textPattern, których ułatwienia dostępu implementują IAccessible::put_accValue (legacyIAccessible rezerwowy).
WinUI 3 RichEditBox i WPF RichTextBox są wyjątkami — uwidaczniają tylko wzorzec tekstowy tylko do odczytu (bez wzorca wartości możliwej do ustawienia), aby nie można było ustawić ich programowo; należy użyć send-keys (wymagany pulpit interaktywny) do wpisywania w nich.
Troubleshooting
| Error | Przyczyna | Rozwiązanie |
|---|---|---|
| "Nie znaleziono uruchomionej aplikacji" | Aplikacja nie działa lub niezgodność nazw | Sprawdzanie nazwy procesu lub używanie identyfikatora PID |
| "Dopasowanie wielu okien" | Niejednoznaczna -a wartość |
Użyj -w <HWND> z wymienionych opcji |
| "ma wiele okien" | Proces ma wiele okien | Użyj -w <HWND> polecenia , aby kierować do określonego elementu |
| "Selektor pasował do N elementów" | Niejednoznaczny selektor starszej wersji | Użyj slugs z inspect danych wyjściowych lub dołącz [0]element , [1] do starszych selektorów |
| "Element mógł ulec zmianie" | Skrót Slug nie pasuje do bieżącego elementu |
inspect Uruchom ponownie lubsearch, aby uzyskać świeże ślimaki |
| "nie obsługuje żadnego wzorca wywołania" | Nie można wywołać elementu | Użyj inspect elementu w celu znalezienia elementu podrzędnego z możliwością wywołania |
| "Nie znaleziono okna UIA" | Interfejs użytkownika nie widzi procesu | Użyj list-windows polecenia , aby znaleźć HWND, a następnie -w |
| "Okno ma zerowy rozmiar" | Okno jest zminimalizowane | Aplikacja zostanie przywrócona automatycznie |
| Wyskakujące okienko/lista rozwijana nie są na zrzucie ekranu | Przechwytywanie domyślne to okno i nie obejmuje nieumyślnych nakładek | Użyj --capture-screen flagi |
element_not_found podczas rejestrowania |
Selektor podany, ale bez pasującego elementu |
inspect Uruchom ponownie lubsearch, aby uzyskać nowy selektor |
| Usługa WGC jest niedostępna podczas rejestrowania | Nie można przechwycić init przechwytywania WGC; brak cichego powrotu | Sprawdź procesor GPU/sterownik; użyj --capture-screen polecenia , aby wyrazić zgodę na przechwytywanie ekranu kontrolera domeny |
Typowe wzorce
Nawigowanie i weryfikowanie
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
Znajdowanie tekstu i wywoływanie jego elementu nadrzędnego
# 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
Uściślanie zduplikowanych elementów
winapp ui search '#Image' -a myapp; winapp ui invoke itm-image-a2b3 -a myapp
Zrzut ekranu przedstawiający wyskakujące nakładki
winapp ui set-value txt-searchbox-e5f6 "query" -a myapp; winapp ui screenshot -a myapp --capture-screen
Nawigowanie, oczekiwanie i weryfikowanie (pojedynczy łańcuch)
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
Odnajdywanie, klikanie i weryfikowanie
winapp ui inspect -a myapp --interactive; winapp ui invoke btn-submit-7a90 -a myapp; winapp ui screenshot -a myapp
Interakcja okna dialogowego pliku
Okna dialogowe otwierania/zapisywania plików to standardowe okna dialogowe Windows z obsługą interfejsu użytkownika:
# 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>
Użyj inspect -w <dialog-hwnd> --interactive polecenia , aby odnaleźć rzeczywiste ślimaki dla określonego okna dialogowego.
Dlaczego ; łańcuch (nie &&)
Operator programu PowerShell może blokować się, gdy natywny && interfejs wiersza polecenia zapisuje w programie stderr lub używa sekwencji ucieczki ANSI. Zamiast tego — ; uruchamia każde polecenie bezwarunkowo i unika tego zakleszczenia. Jest to również lepsze w przypadku przepływów pracy agenta: zwykle chcesz, aby zrzut ekranu był uruchamiany nawet wtedy, gdy wywołanie miało wyjście niezerowe.
Wzorce testowania ciągłej integracji
Użyj winapp ui poleceń w potokach ciągłej integracji (GitHub Actions, Azure DevOps) na potrzeby testów weryfikacyjnych kompilacji i weryfikacji interfejsu użytkownika.
wait-for z --property i --value działa jako asercja — zwraca kod zakończenia 1 w przypadku przekroczenia limitu czasu, co powoduje automatyczne niepowodzenie kroku ciągłej integracji.
Uruchamianie i testowanie w 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
Stan elementu assert z wait-for
wait-for --value sonduje, dopóki wartość elementu nie pasuje do oczekiwanego ciągu, używając tego samego inteligentnego rezerwowego co get-value (TextPattern → ValuePattern → SelectionPattern → Name). Zwraca kod zakończenia 0 zgodny, kod zakończenia 1 w przypadku przekroczenia limitu czasu — co czyni go asercją przyjazną dla ciągłej integracji. Zamiast tego użyj polecenia --property , aby sprawdzić określoną właściwość 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
Potwierdzanie przy użyciu danych wyjściowych JSON
Używanie z --json programem PowerShell lub jq w celu uzyskania bardziej złożonych asercji:
Kontrakt zakończenia kodu dla
searchiwait-forw--jsontrybie: gdy żaden element nie pasuje (search) lub limit czasu oczekiwania (wait-for), polecenie zapisuje w pełni analizowalne koperty wyniku do stdout ({ "matchCount": 0, ... }lub{ "found": false, "timedOut": true, ... }) i zwraca kod zakończenia 1. Stderr jest pusty w--jsontrybie (dane wyjściowe rejestratora są pomijane). Rozgałęzij na polach koperty lub na$LASTEXITCODE, w zależności od tego, co jest bardziej ergonomiczne.
# 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)" }
Przykład pełnego testu weryfikacyjnego kompilacji
# 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