Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Inspektera och interagera med att köra Windows program från kommandoraden. Används av AI-agenter och utvecklare för gränssnittstestning, felsökning och automatisering.
Översikt
winapp ui innehåller kommandon för att inspektera och interagera med Windows app-UIs.
Använder Windows UI Automation (UIA). Fungerar med alla Windows appar – WPF, WinForms, Win32, Electron och WinUI 3.
De flesta kommandon styr appen via UIA-mönster (ingen inmatning). Undantagen matar in verkliga indata: ui click/ui hover/ui draganvänd mussimulering,ui touch/ui pen syntetisera pek- och penn-/pennaindata och ui send-keys syntetiserar tangentbordsindata – för kontroller och scenarier som UIA-mönster inte kan köra.
Important
Krav för interaktivt skrivbord (indatainmatningsverb).click, hover, drag, touch, pen, scroll --wheeloch send-keys --via send-input syntetiserar indata på OS-nivå, så de behöver ett olåst interaktivt skrivbord med målfönstret i förgrunden. På en låst arbetsstation eller ett säkert skrivbord (LogonUI/UAC) kan de inte mata in och misslyckas snabbt med no_interactive_desktop (skiljer sig från höjd/foreground_not_target fall).
touch
/
pen vägra dessutom när inget fönster matchar (no_target); en koordinat utanför målfönstret är en varning som inte är dödlig (en warnings[] post under --json, eller en varningsrad i textläge) och inmatningen fortsätter fortfarande – i överensstämmelse med musverb. Allt annat – inspect, search, get-property, get-value, wait-for, set-value, , invoke– scroll --direction/--to driver appen genom UIA-mönster och är headless/locked-session friendly.
screenshot är undantaget bland de icke-injicerande verben: det tar en exklusiv tur och dess avbildning kan behöva ett användbart interaktivt skrivbord, eftersom motorn återställer ett minimerat mål och återgår till förgrunden när bildruteavbildningen inte är tillgänglig eller --capture-screen används. Föredrar UIA-mönsterverb i CI; reservera inmatningsverb för scenarier som verkligen behöver verkliga indata. Före inmatningen löser gestverberna också målelementet igen och vägrar med target_moved om det fortfarande animerar/flyttar, i stället för att landa indata på tomt utrymme.
Snabbstart
Kör winapp ui --help för kärnloopen: inspect -a <app> --interactive för att se vad du kan agera på eller set-valueinvoke för att agera och get-value för att kontrollera resultatet. Varje kommando visar --help exempel. Ett okänt kommando, till exempel winapp ui dump, avslutas med kod 1 och föreslår de närmaste kommandona (som ett JSON-fel med suggestions när du skickar --json).
# Connect to any app and see its UI tree
winapp ui inspect -a notepad
# Find specific elements
winapp ui search Button -a notepad
# Activate an element
winapp ui invoke Close -a notepad
# Take a screenshot
winapp ui screenshot -a notepad
Köra automatisering av användargränssnitt i Windows sandbox-miljö
Om du vill hålla automatiseringen borta från skrivbordet lägger du till --on sandbox i körnings- och användargränssnittskommandona:
winapp run . --on sandbox --detach
winapp ui inspect --on sandbox -a MyApp
winapp ui invoke --on sandbox SubmitButton -a MyApp
--detach returnerar efter start; utan den run väntar på att appen ska avslutas. Behåll --on sandbox alla gästkommandon, inklusive de som använder en PID eller ett fönsterhandtag.
Se Windows sandbox-körning för klientkrav, korta ändringar i konfiguration/återanslut fokus, arbetsflödessamordning och leverans av värdutdata.
Begränsade och inskrivna frågor
winapp ui search "Welcome to MyApp" -a myapp --root MailRow --type Text --class-name TextBlock
winapp ui get-value Subject -w 123456 --root MailRow --type TextBox
winapp ui get-property Subject -a myapp --root MailRow --type Edit --property Value
winapp ui wait-for Subject -a myapp --root MailRow --type Edit --value "Ready" --timeout 10000
winapp ui invoke Open -w <dialog-HWND> --type Button
winapp ui set-value "Text editor" "hello" -a notepad --type Document
Dessa kommandon accepterar valfria filter på deras elementväljare: inspect (med en väljare), search, , get-property, get-value, wait-for, invoke, set-value, hoverfocusclick, scroll, scroll-into-view, screenshot, , record, touchoch .pen
drag (två väljare) och send-keys --target gör det inte.
Väljaren och varje angivet filter måste matcha samma element. Filter begränsar en väljare, så inspect, , och record, vars väljare är valfri, misslyckas med invalid_arguments när givna screenshotfilter utan en. För touch och penbehöver filter en väljare. De kan inte kombineras med --at eller --path (invalid_arguments):
-
--root <selector>söker bara efter underordnade till en unikt matchande rot, aldrig själva roten. Använd ett AutomationId eller en snigel fråninspectför att skilja. En rot som matchar flera element misslyckas medambiguous_selector, även om en matchning kan anropas. En rot som saknas genererar inga matchningar. När roten har hittats söker inte frågor i orelaterade popup-fönster, även om inga underordnade matchar. Frågor begränsas inte avinspectvisningsdjupet. -
--type <control-type>matchar en UIA-kontrolltyp och ignorerar skiftläge. De enda aliasen ärTextBox→EditochTextBlock→Text. Okända namn (inklusive numeriska ID:n och jokerteckenuttryck) misslyckas medinvalid_arguments. -
--class-name <literal>matchar leverantörens hela UIAClassNameoch ignorerar ärendet. Det är inte ett substring, jokertecken eller reguljärt uttryck. Användget-property --property ClassNameför att identifiera providerns värde. Klassnamnet behöver inte vara lika med UIA-kontrolltypen.
Filtrerade frågor använder UIA:s kontrollvy, samma vy som visas av inspect.
Providernoder som endast exponeras i raw-vyn returneras inte. används inspect för att hitta den innehållande kontrollen och dess väljare.
Alla 41 officiella typer stöds: Button, Calendar, CheckBox, ComboBox, Edit, Hyperlink, Image, ListMenuBarListItemMenuItemMenuProgressBarRadioButton, SliderThumbTreeItemTabItemStatusBarTextSpinnerToolBarCustomScrollBarTabTreeGroupToolTip, , DataGrid, , DataItem, Document, , SplitButton, PaneWindow, Header, HeaderItem, Table, TitleBar, Separator, . SemanticZoomAppBar
wait-for löser rotväljaren igen vid varje omröstning, så roten kan visas när kommandot startar. Med --goneinnebär en frånvarande rot att det inte finns någon matchande underordnade. En tvetydig rot är ett fel, inte en framgång.
Ett avbrutet uppslag är inte ett bevis på försvinnande: om ett element tas bort under uppslag eller ersätts före en --value läsning, kontrolleras nästa avsökning igen. Andra uppslags- eller läsfel misslyckas med kommandot.
-w <HWND> begränsar rotidentifieringen till fönstrets UIA-träd. Med -akan rotidentifiering också hitta appens popup-fönster. Exakta AutomationId-rotmatchningar har företräde framför delsträngsmatchningar i alla dessa fönster. flera exakta matchningar misslyckas fortfarande med ambiguous_selector.
En rotsnigel väljer det elementet även när ett annat fönster har samma AutomationId. Om den valda roten ersätts matchar den gamla snigeln inte längre; använd ett AutomationId eller en namnrot när du vill att avsökningen ska följa en ersättning.
När filter finns misslyckas alla kommandon förutom search med ambiguous_selector om fler än ett element finns kvar. Begränsa filtren eller använd en unik snigel. Kommandon som fungerar på antalet element matchar i varje fönster som de söker i, så en matchande kontroll i en ägd dialogruta gör också väljaren tvetydig. Exact AutomationId matchar behåll prioritet framför delsträngsmatchningar inom det filtrerade omfånget. Om du utelämnar alla tre alternativen bevaras det befintliga frågebeteendet.
Samordna samtidiga gränssnittsarbetsflöden
Windows har bara ett förgrundsfönster, ett tangentbordsfokus, en markör och en indataström. När två winapp ui arbetsflöden körs på samma inloggade skrivbord samtidigt kan de stjäla fokus från varandra, stänga en meny som den andra precis öppnat eller flytta ut ett mål under ett väntande klick.
Skiljeförfarande är alltid på. Varje winapp ui kommando som berör det fysiska skrivbordet tar en sväng, utan konfiguration och inget sätt att stänga av det, så att två agenter aldrig kan skriva in i varandras fönster. Skrivskyddade kommandon fortsätter att köras samtidigt. Det enda undantaget är en process som inte kan komma åt winapps samordningsmapp, till exempel en agents sandbox-miljö som blockerar %USERPROFILE%\.winapp: dess kommandon körs fortfarande, men utan att turas om, och skriva ut en varning (förutom med --json eller --quiet).
Kontinuitet mellan kommandon är anmälning. Som standard är varje kommando ett fristående enskott: det väntar sin tur, gör sitt arbete och släpper skrivbordet omedelbart. Om du vill behålla skrivbordet i flera kommandon ger du dem samma arbetsflödes-ID:
# Set once per logical UI workflow
$env:WINAPP_UI_WORKFLOW_ID = [guid]::NewGuid().ToString()
Vad du behöver veta:
- Ett arbetsflödes-ID namnger ett logiskt arbetsflöde – inte nödvändigtvis en hel agent och inte nödvändigtvis en app. Använd samma värde för samarbetskommandon (en inspelning plus de klick som ska avbildas). använd olika värden för oberoende arbetsflöden, även när en agent startar båda.
- Utan ID är varje kommando ett oberoende enskott. Det skiljedomar fortfarande, men det banker ingen nåd och ger skrivbordet av det ögonblick det slutar. Två no-id kommandon är separata arbetsflöden även när de startas från samma gränssnitt.
- Fresh-shell och adaptiva värdar måste mata in samma värde. Om varje kommando körs i ett nytt gränssnitt – vilket är hur de flesta agentverktyg anropar arbete – är det enda som kan gruppera dem en explicit
WINAPP_UI_WORKFLOW_IDvidarebefordrad till varje samarbetande anrop. - Den fyra sekunder långa respiten skyddar snäva skurar, inte modellskäl. Ett arbetsflöde med ett ID behåller sin tur så länge nästa kommando startar inom fyra sekunder. Det omfattar back-to-back-kommandon i ett skript. den upphör avsiktligt att gälla medan en modell tänker. Det är en reserv för när du inte kan säga att du är klar – när du kan, kör
winapp ui yieldi stället för att vänta ut den. - Anpassningsbara arbetsflöden måste återskapas, återanvändas och spelas upp igen. Efter ett resonemangsgap kan ett annat arbetsflöde ha använt skrivbordet, så öppna menyn igen, lös elementet igen och agera sedan. Skicka kända sekvenser från slutpunkt till slutpunkt som ett tätt skript i stället för att hålla skrivbordet medan du tänker.
- Beställningen är ägartillhörighet först, sedan FIFO bland de andra. Även om ett arbetsflöde är aktivt eller inom dess respit kan det fortsätta att utfärda kommandon, även om andra arbetsflöden redan väntar. När den körs
winapp ui yieldeller dess respit upphör att gälla, hanteras väntande arbetsflöden i strikt ankomstordning. Kontinuerlig aktivitet av ett arbetsflöde kan därför fördröja andra på obestämd tid. - Det finns ingen hård keps. Ett långt skript, en obundna inspelning eller en felloop kan blockera andra muterande arbetsflöden.
-
Annullering eller processavslut är återställningen för ett fast live-arbetsflöde. Väntande kommandon skriver ut en status efter en sekund och kan stoppas med
Ctrl+C, som avslutar130. - Endast kompatibla uppdaterade binärfiler samarbetar. Äldre
winappversioner förebygger den här funktionen och är inte samordnade. Kod som anropar UI Automation NuGet-paket direkt ligger utanför den här garantin helt och hållet – samordningen finns i CLI, inte i paketen.
Vilka kommandon väntar på en sväng:
| Behavior | Commands |
|---|---|
| Körs samtidigt (väntar aldrig) |
status, list-windows, inspect, , search, get-property, get-value, , get-focused, wait-for |
| Väntar på svängen men tar aldrig skrivbordet |
set-value, scroll-into-view, , scroll --direction/--torecord |
| Väntar på svängen och tar skrivbordet exklusivt |
invoke, click, drag, hover, scroll --wheel, touch, , pen, focus, , send-keysscreenshot |
Den mellersta raden är den som är värd att förstå.
set-value, scroll-into-view och scroll --direction/--to driver UIA-mönster i stället för förgrunden, så att de förblir huvudlösa/låsta och blockerar aldrig någon från att använda skrivbordet. Men de ändrar vad appen visar, så de väntar bakom ett annat arbetsflödes tur i stället för att redigera ett fält eller rulla ut en lista under någon annans klick.
I ett arbetsflöde överlappar de med annat delat arbete – det är så ett record avbildar de anrop som set-value spelas in. De ignorerar inte det egna arbetsflödets framåtriktade barriär: ett tidigare DesktopExclusive kommando för samma arbetsflöde (en click, a screenshot) blockerar dem fortfarande, precis som det blockerar varje senare kommando, så ett klick och mutationen som följer det förblir i den ordning du skrev dem.
screenshot alltid köar för en exklusiv sväng. Inte alla bilder stör skrivbordet – ett vanligt synligt fönster som fångas genom Windows Grafikinsamling inte gör det – men motorn återställer målet om det minimeras och återgår till förgrundsbild när bildruteavbildningen inte är tillgänglig eller --capture-screen läser liveskärmen. Dessa behöver bara ytan när avbildningen är igång, så kommandot tar svängen uppåt i stället för att gissa. När det sammansatta flera fönster det fångar dem alla under en exklusiv tur, så den sparade bilden är ett enda konsekvent ögonblick snarare än en blandning av före och efter. Kodning och skrivning av filen sker när skrivbordet har släppts.
--capture-screenbehöver exakt ett fönster. Live-screen capture registrerar vad som faktiskt finns framför, och endast ett fönster kan vara. Om du väljer ett fönster explicit med-w <hwnd>får du exakt en region – bildpunkterna inuti fönstrets gränser, inklusive valfri dialogruta eller överlägg synligt ovanpå det, vilket är anledningen till att läsa skärmen i första hand. När-amatchar flera översta eller ägda fönster finns det inget sådant val, så kommandot misslyckas medinvalid_argumentsinnan något fångas i stället för att bekämpa förgrunden. Körwinapp ui list-windows -a <app>och försök igen med-w <hwnd>, eller släpp--capture-screenför att sammansatta varje fönster från sitt eget innehåll.
record delar sin tur så att indata för samma arbetsflöde kan sammanlänkas med avbildningen – det är så du registrerar ett arbetsflöde som kör en app. Två varningar:
- Ett
recordmed inget arbetsflödes-ID är en one-shot-ägare, så det blockerar alla andra arbetsflöden under hela dess varaktighet. Om du vill spela in och klicka samtidigt ger du båda kommandona sammaWINAPP_UI_WORKFLOW_ID. - På en värd utan stöd för frame-capture återgår inspelningen till PrintWindow, vars återställning med tom bildruta kan förgrunda fönstret när som helst. Där finns skrivbordet för hela inspelningen och kommandot säger så i sina utdata; även indata för samma arbetsflöde väntar.
Fel som du kan se: invalid_ui_workflow_id (variabeln är inställd men tom eller över 256 tecken), desktop_coordination_unavailable (koordinationstillståndet är oläsligt och kan inte återskapas på ett säkert sätt, eller skrevs av en nyare winapp), queue_capacity_exceeded (64 kommandon från andra arbetsflöden väntar redan – gränsen räknar live utländska servitörer, inte processer som du har startat, så poster som tillhör kommandon som har avslutats eller dödats upptar inte ett fack, och ditt eget arbetsflödes kommandokö bakom varandra i stället för mot den här gränsen), ui_turn_busy (yield medan ditt eget arbetsflöde fortfarande har ett kommando som körs) och cancelled (Ctrl + C medan du väntar, avsluta koden 130).
Släpper svängen tidigt: winapp ui yield
Den fyra sekunder långa respiten är en reserv: den håller skrivbordet reserverat när du inte kan säga säkert att du är klar. När du kan säga så, säg så - yield händer skrivbordet över omedelbart istället för att få alla andra att vänta ut en nåd som ingen behöver.
$env:WINAPP_UI_WORKFLOW_ID = [guid]::NewGuid().ToString()
winapp ui invoke File -a notepad
winapp ui click "Save As..." -a notepad
winapp ui set-value txt-filename-a1b2 "notes.txt" -a notepad
winapp ui yield # done — a waiting workflow starts now, not in four seconds
- One-shot-kommandon bör inte ange något arbetsflödes-ID alls. Utan en släpper varje kommando redan skrivbordet så fort det är klart, och det finns inget att ge.
- Arbetsflöden i flera steg bör ge resultat när de är klara, särskilt när andra arbetsflöden kan vänta. Det kostar ett snabbt kommando och tar bort ett fyra sekunders bås från alla andra.
- Det är idempotent. Att ge två gånger, eller efter att respiten redan har upphört, lyckas och rapporterar
{ "released": false }– det är den normala änden av ett skript, inte ett fel. - Det släpper aldrig ett annat arbetsflödes tur. Om någon annan har skrivbordet, eller om ingen gör det, är det en no-op.
- Det misslyckas med
ui_turn_busyom ditt eget arbetsflöde fortfarande har ett kommando som körs eller köas – en inspelning, till exempel. Om du släpper under det skulle skrivbordet tas bort mitt i kommandot, så inget släpps och kommandot som körs påverkas inte. Vänta på det eller stoppa det och ge sedan igen. - Det kräver
WINAPP_UI_WORKFLOW_ID. Utan en misslyckas den medinvalid_arguments. - Det tar ingen app och ingen väljare: den ger tillbaka en reservation, inte ett fönster, så det fungerar fortfarande när appen har stängts.
Ett väntande kommando väcks av den som släpper skrivbordet i stället för att söka efter det, så en kö kostar nästan ingenting medan den väntar och överlämningen är omedelbar. Varje servitör kontrollerar också på egen hand ibland, vilket är vad som återställer skrivbordet när en process dödas och aldrig publicerar något: kommandot i köns huvud ser ut varje halv sekund och kommandon bakom det - som inte kan köras innan huvudet gör det ändå - med några sekunders mellanrum.
Rikta in sig på appar
Efter processnamn
winapp ui inspect -a notepad
winapp ui inspect -a slack # auto-picks visible window for multi-process apps
winapp ui inspect -a imageresizer # partial match: finds PowerToys.ImageResizer
winapp ui search Seven -a calculator # hosted app: uses the frame window that hosts it
Vissa paketerade appar (till exempel Kalkylatorn) har inget eget fönster; en annan process är värd för sin ram. När den matchade processen (efter namn eller PID) inte har något synligt fönster -a använder du den ram som är värd för dess innehåll i stället. Om det inte finns någon (till exempel om appen fortfarande startar) -a riktas processen mot processen, så wait-for fortsätter att titta tills dess fönster visas.
Efter fönsterrubrik
winapp ui inspect -a "LICENSE - Notepad"
winapp ui inspect -a "Fix WinApp" # partial title match
Efter PID
winapp ui inspect -a 12345
Efter HWND (stabil – överlever tab-/titeländringar)
# 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
Används -a för identifiering -w för stabil inriktning. När -a matchar flera fönster listar kommandot dem med HWND:er som du kan välja.
Väljare
Målelement med väljaren som visas i [brackets] inspektera/söka utdata.
Det finns tre typer av väljare:
| Selector | Meaning | Example |
|---|---|---|
MinimizeButton |
AutomationId (visas när det är unikt – stabilt, prioriterat) | winapp ui invoke MinimizeButton -a myapp |
btn-close-d1a0 |
Semantisk snigel (visas när inget unikt AutomationId) | winapp ui invoke btn-close-d1a0 -a myapp |
Submit |
Oformaterad textsökning mot Namn/AutomationId (skiftlägesokänslig understräng) | winapp ui invoke Submit -a myapp |
AutomationId-väljare är identifierare för utvecklaruppsättningar (AutomationProperties.AutomationId i XAML).
När ett AutomationId är unikt i hela användargränssnittsträdet inspect och search visar det direkt som väljare – dessa överlever layoutändringar, lokalisering och trädomstrukturering.
Snigelväljare (t.ex. btn-close-d1a0) genereras när det inte finns något unikt AutomationId.
Format: prefix-name-hash. Hashen validerar elementidentiteten men kan bli inaktuell efter ändringar i användargränssnittet.
Granska utdataformat
Kommandot inspect visar elementträdet med färgade utdata (väljare i cyan, namn i grönt, metadata i grått):
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
Det första ordet på varje rad är väljaren – använd det med andra ui kommandon.
När ett element har ett unikt AutomationId används det direkt (t.ex. TabView, NewTabButton).
När det inte finns något unikt AutomationId används en genererad snigel (t.ex. tab-newtab-5f5b).
Semantiska sniglar
Sniglar använder formatet: prefix-normalizedname-hash där:
- prefix – förkortning av 3-bokstavstyp (btn, txt, chk, cmb, itm, tab, img, lbl, pn, win, grp, lnk, mnu osv.)
- normalizedname – gemener alfanumeriskt från AutomationId (föredraget) eller Namn, max 15 tecken
- hash – 4-teckens hex-hash för elementets RuntimeId (validerar elementidentitet)
Sniglar är skalsäkra (inga specialtecken), unika och kan användas direkt som argument. Utan frågefilter ger hashen föråldringsidentifiering – om elementet har ersatts får du: "Elementet kan ha ändrats. Kör om inspektionen." För filtrerade frågor, se Omfångsbegränsade och inskrivna frågor.
Element utan namn eller AutomationId visar endast prefix + hash (t.ex. pn-c8a3).
Tvetydiga flera matchningar
Sniglar från inspect/search utdata är unika, men kan ändras mellan layoutändringar – använd dem över oformaterade typnamn eller text när flera matchningar. När en väljare är tvetydig skriver CLI ut alla matchningar med sina sniglar så att du kan välja rätt och köra igen med den snigeln.
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
Oformaterad textsökning
Använd oformaterad text för att söka efter element – ingen särskild syntax krävs:
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
När en textsökning matchar flera element (t.ex. InställningarExpander där grupp, knapp och text alla delar samma namn) väljer CLI automatiskt det enda anropsbara elementet. Om flera kan anropas visas alla matchningar med sniglar.
För sökresultat som inte kan anropas (t.ex. en TextBlock inuti en knapp) visas automatiskt den närmaste anropsbara överordnad - det överordnade elementet som du kan använda med invoke.
Detta fungerar för alla sökväljare:
lbl-savechanges-a1b2 "Save changes" (120,40 80x20)
^ invoke via: btn-save-c3d4 "Save"
Väljaren som visas kan användas direkt:
winapp ui invoke btn-save-c3d4 -a myapp # invoke the parent Button
Commands
status
Anslut till en app och visa anslutningsinformation.
winapp ui status -a notepad
winapp ui status -a notepad --json
Inspektera
Visa elementträdet för användargränssnittet. Utdata visar semantiska sniglar med indrag med två blanksteg för hierarki:
winapp ui inspect -a notepad # full window tree, depth 3
winapp ui inspect -a notepad --depth 5 # deeper tree
winapp ui inspect txt-searchbox-e5f6 -a notepad # subtree rooted at element
winapp ui inspect --ancestors btn-close-d1a2 -a notepad # walk up from element to root
winapp ui inspect -a myapp --interactive # elements you can invoke, click, or set-value; auto-depth 8
winapp ui inspect -a myapp --hide-disabled # hide disabled elements
winapp ui inspect -a myapp --hide-offscreen # hide offscreen elements
Exempelutdata (standard):
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)
Exempelutdata (--interactive – endast åtgärdsbara element, platt lista):
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)
Element kan visa dessa tillståndsmarkörer:
-
[on]/[off]/[indeterminate]— växla/kryssrutetillstånd -
[collapsed]/[expanded]— expandera/komprimera tillstånd för träd, kombinationsrutor, menyalternativ -
[scroll:v]/[scroll:h]/[scroll:vh]— rullningsbar container (lodrät, vågrät eller båda) -
[offscreen]— elementet visas inte på skärmen -
[disabled]— elementet är inte aktiverat -
value="..."— aktuellt textinnehåll för redigerbara element (när det skiljer sig från Namn)
search
Hitta element som matchar en väljare. Utdata visar semantiska sniglar:
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
Exempel på utdata:
btn-minimize-d1a0 "Minimize" (1222,206 48x48)
btn-maximize-e2b1 "Maximize" (1270,206 48x48)
btn-close-d1a2 "Close" (1318,206 48x48)
Sniglar som visas i utdata (t.ex. btn-minimize-d1a0) kan användas direkt med andra kommandon:
winapp ui invoke btn-minimize-d1a0 -a notepad
get-property
Läsa egenskapsvärden från ett element. Innehåller mönsterspecifikt tillstånd (ToggleState, Value, IsSelected osv.).
winapp ui get-property btn-submit-7a90 -a myapp # all properties
winapp ui get-property chk-checkbox-b2c3 -p ToggleState -a myapp # checkbox state
winapp ui get-property txt-textbox-a4b1 -p Value -a myapp # current text value
winapp ui get-property cmb-combobox-d5e6 -p ExpandCollapseState -a myapp # expanded or collapsed
winapp ui get-property Document -p FontWeight -a myapp --json # document formatting
Egenskapsnamn är skiftlägeskänsliga. Ett okänt namn misslyckas med invalid_arguments under --json; utelämna --property för att visa egenskaperna, inklusive alla sex textformateringsattributen nedan.
wait-for --property använder samma skiftlägeskänsliga namn och avvisar okända namn före avsökning.
Textformatering i hela dokumentet
Formatering läss över hela elementets TextPattern-dokument, inte dess aktuella markering eller caret. Läsningar ändrar inte fokus eller markering.
| Property | Enhetligt värde (returneras som en sträng) |
|---|---|
FontWeight |
Numerisk vikt, till exempel "400" (normal) eller "700" (fetstil) |
FontName |
Teckensnittsfamiljenamn, till exempel "Courier New" |
FontSize |
Storlek i punkter, till exempel "15.5" |
ForegroundColor |
Decimal Windows COLORREF (0x00BBGGRR), till exempel "3678732" för RGB(12, 34, 56) |
IsItalic |
"True" eller "False" |
StrikethroughStyle |
Numerisk UIA-textdekorationsstil, till exempel "0" (ingen) eller "1" (enkel) |
Tal använder invariant formatering (en decimalpunkt, oavsett språkvariant). Varje attribut kan i stället returnera:
| Value | Innebörd och nästa steg |
|---|---|
"Mixed" |
Formateringen varierar i dokumentet. Behandla det inte som ett enhetligt värde; det här kommandot kör inte frågor mot enskilda textintervall. |
"NotSupported" |
Dokumentets TextPattern-provider rapporterar inte det här attributet. Kontrollera appens hjälpmedelsstöd. |
"Unavailable" |
Elementet har ingen TextPattern. Använd inspect eller search för att hitta dess text-/dokumentelement. |
När du listar alla egenskaper förblir cachelagrade grundläggande egenskaper tillgängliga om inget live-element kan matchas och ett felaktigt formateringsvärde utelämnas utan att andra egenskaper tas bort. Dessa utelämnanden loggas som varningar. Begär en specifik formateringsegenskap för att få ett fel i stället för ett utelämnande.
Providerfel förblir fel, inte "Unavailable". För stale_elementkontrollerar du appen igen och försöker igen med en aktuell väljare.
JSON-kuvertet innehåller elementId, ett skrivet elementoch strängvärde properties.
Befintliga egenskaper, inklusive BoundingRectangle, behåller sina format.
Formateringsdelen av properties är till exempel:
{
"FontWeight": "700"
}
skärmbild
Avbilda ett fönster eller element som PNG.
winapp ui screenshot -a notepad # saves screenshot.png in cwd
winapp ui screenshot -a notepad --output my.png # custom filename
winapp ui screenshot --quiet -a notepad -o my.png # save without informational output
winapp ui screenshot -a notepad --json # returns file path as JSON
winapp ui screenshot -w 131906 # target specific HWND (+ its dialogs)
winapp ui screenshot txt-searchbox-e5f6 -a myapp # crop to element bounds
winapp ui screenshot -w 131906 --capture-screen # one screen region, with visible overlays in place; foregrounds window
winapp ui screenshot -a myapp --focus # bring window to foreground first, then capture (default WGC path)
Utan en elementväljare kombinerar standardavbildningen flera fönster i ett märkt sammansatt PNG sida vid sida, inte separata filer.
-a efter processnamn eller PID innehåller appens fönster och deras ägda fönster. En rubrikbaserad -a matchning väljer ett matchande fönster plus dess ägda fönster. -w Väljer uttryckligen ett fönster plus dess ägda fönster, inte alla fönster i processen. En ägd dialogruta eller knappbeskrivning kan därför visas som en egen panel även när du uttryckligen väljer huvud-HWND. En elementväljare beskär det elementet i stället för att skapa fönster. Ett element i en meny, utfälld meny, knappbeskrivning eller ett undervisningstips som öppnas i ett eget popup-fönster beskärs från det popup-fönstret, inte från fönstret bakom det.
--quiet undertrycker informationsutdata för både enskilda fönster och sammansatta avbildningar, inklusive den sparade sökvägen. Varningar och diagnostik för avbildningsfel förblir synliga. Använd --json i stället när du behöver filsökvägen och dimensionerna som strukturerade utdata.
Med --on sandboxnamnger --output du värdmålet. Lyckade oformaterade utdata och --json rapportera värdsökvägen efter att avbildningen har levererats.
Standardsökvägen för avbildning använder Windows. Graphics.Capture (WGC) läser den faktiska DWM-sammansatta ytan – bevarar rundade hörn, transparens och arbete även när fönstret är ockluderat av andra windows. Om WGC inte är tillgängligt (äldre Windows versioner) återgår CLI till PrintWindow.
Använd --capture-screen -w <hwnd> när du behöver synliga popup-fönster eller knappbeskrivningar i deras positioner på skärmen, inklusive överlägg som inte ägs av målfönstret. Det läser fönstrets skärmregion i stället för att skriva etiketterade paneler och tar fönstret till förgrunden först. Med -akräver det exakt ett matchande fönster. Om flera översta eller ägda fönster matchar använder winapp ui list-windows -a <app> du och försöker igen med -w <hwnd>. Använd --focus om du bara vill förgrunda fönstret utan att växla avbildningslägen (t.ex. för att säkerställa att skärmbilden matchar det som användaren för närvarande tittar på).
Eftersom skärmen DC fångar vad som faktiskt framför,
--capture-screenverifierar målet nådde förgrunden omedelbart innan fånga och misslyckas medforeground_not_targetom det inte (fokus-stjäla förebyggande, en UAC prompt eller ett annat fönster aktivera sig). Ingen bild är skriven i det fallet – tidigare avslutade kommandot 0 och lämnade tillbaka en bild av fel fönster.ui record --capture-screensamma kontroll före den första ramen.
rekord
Registrera ett fönster eller en elementregion till en H.264 MP4. Föredrar en positiv --duration-sec för obevakade skript. Utan varaktighet fortsätter inspelningen tills Ctrl+C eller, för omdirigerad stdin, en ny rad eller EOF. Npm uiRecord och targetRecord hjälpare kräver ett heltal durationSec från 1 till 86400; deras abortsignal avbryts kraftfullt snarare än att graciöst slutföra en inspelning.
# Record for 10 seconds
winapp ui record -a myapp --duration-sec 10 --fps 15 --output demo.mp4
# Add agent-readable frames
winapp ui record -a myapp --frames --duration-sec 10 --fps 10 --output evidence.mp4 --json
# Stop an unbounded recording through stdin
"" | winapp ui record -a myapp --json --output capture.mp4
# Include screen overlays and popups
winapp ui record -a myapp --capture-screen --duration-sec 5 --output with-popups.mp4
Alternativ:
-
--duration-sec N— Spela in i N sekunder. Standard 0 poster tills de har stoppats. -
--fps N— Målbildrutor per sekund (standard 15). -
--max-edge N— Nedskala så att den längsta kanten är högst N pixlar (0 = ingen nedskalning). -
--capture-screen– Avbilda från skärmens domänkontrollant (innehåller överlägg/popup-fönster, förgrunder i fönstret). -
--output <path>— Utdata-MP4-sökväg. Standardinställningen ärrecording-<timestamp>-<guid>.mp4. -
--overwrite— Ersätt befintliga inspelningsutdata när den nya tagning har slutförts. Utan den avvisas befintliga utdata. -
--frames— Skriva tidsstämplad JPEG-bevis till<output-name>.frames. Stöder 1-30 fps och--max-edge64-4096 (standard 1280). Ramdata är begränsade till 1 GiB; MP4 fortsätter om taket nås.
Agentläsbara ramartefakter:
evidence.mp4
evidence.frames/
manifest.json
frames.ndjson
frames/
frame-000000-t000000000012.jpg
frames.ndjson har en rad per exempel med sampleIndex, monoton elapsedMs, MP4-relativ mediaTimeMs, imageIndex, fileoch changed. På varandra följande pixel-identiska exempel återanvänder föregående quality-85 JPEG.
manifest.json registrerar begäran, tidsinställning, MP4-status, bilddimensioner och status (complete, partialeller truncated). Trunkerad tidsinställning omfattar det behållna prefixet, medan video den fullständiga MP4-koden beskrivs.
Välj en ny utdatasökväg om du inte tänker ersätta en inspelning med --overwrite.
Utan den blockerar antingen en befintlig video eller dess kopplade .frames katalog inspelning, även om du utelämnar --frames.
Den tidigare MP4 förblir intakt om den nya avbildningen misslyckas. Vid lyckad ersättning behålls den tidigare ramkatalogen som <output-name>.frames.previous-<id>, även om den nya inspelningen utelämnar --frames. Bevara partiella bevis och följ de rapporterade recoveryHint innan du försöker igen. Om MP4-slutförande misslyckas kan bevarade ramar publiceras under <output-name>.frames.partial-*. Ramartefakter innehåller okrypterat skärminnehåll. hantera dem som skärmbilder eller video.
Med --on sandboxlevereras både MP4- och ramkatalogen till värden, inklusive standardutdata när --output utelämnas. Se Sandbox-avbildning för avbrutna inspelningar och helskrivbordsavbildning.
Avbildningslägen (rapporteras i JSON-fältet mode ):
-
wgc— Windows Grafikfångst (standard; fungerar medan fönstret är occluded). -
printwindow— GDI PrintWindow (återställning när WGC inte är tillgänglig i det här systemet/sessionen; kör igen med--capture-screenför att använda skärm-DC i stället). -
screen— Skärm-DC via--capture-screen(innehåller överlägg/popup-fönster; för fönstret till förgrunden).
JSON-utdataformat (--json):
-
stdout: Slutligt inspelningsresultat, inklusive kadens, stopporsak, valfria
frameArtifactsoch varningar. -
stderr: Ett JSON-objekt per rad: en
recording-startedhändelse efter den första ramen, följt av ett fel om inspelningen misslyckas senare. Ramsökvägar ingår endast när bildruteutdata är aktiva.
Felkoder:
-
element_not_found— Väljaren matchade inte. -
ambiguous_selector— Väljaren matchade flera element. använd en föreslagen snigel. -
invalid_arguments— Ett alternativvärde är ogiltigt. -
output_exists— Det finns redan en inspelningsutdata och kan inte ersättas under de begärda alternativen. -
frame_output_failed— Ingen artefakt kunde bevaras när bildruteutdata misslyckades. -
partial_output— Endast en artefakt har slutförts. inspekterapartialOutputochrecoveryHint.
En elementväljare registrerar det elementets region från det fönster som det ritas i. För ett objekt i en meny, en utfällbara meny, knappbeskrivning eller ett undervisningstips som öppnas i ett eget popup-fönster, visar inspelningen popup-fönstret snarare än fönstret bakom det.
Åberopa
winapp ui invoke SettingsCategory -a myapp --action select
winapp ui invoke AgreeCheckbox -a myapp --action toggle-on --json
winapp ui invoke SizeComboBox -a myapp --action expand
winapp ui invoke Open -w <dialog-HWND> --root Actions --type Button --class-name Button --action invoke
winapp ui invoke SubmitButton -a myapp
Använd --action när ett test måste utföra en specifik åtgärd på exakt det valda elementet. Det försöker aldrig något annat mönster eller en anropsbar överordnad, även om den begärda åtgärden misslyckas. En kontroll som stöder både anrop och val väljs, inte anropas, med --action select. Med --actionär en snigel inriktad på exakt ett element. En oformaterad text- eller AutomationId-väljare som matchar fler än ett element misslyckas med en icke-nollavslutskod i stället för att agera på den första matchningen, så skicka en snigel från inspect/search när ett namn är tvetydigt.
--root, --type, och --class-name begränsa matchningen enligt beskrivningen i Begränsade och inskrivna frågor, med eller utan --action.
Använd -w <dialog-HWND> för att begränsa en åtgärd till den dialogrutan eller -a <app> för att inkludera appens fönster. En filtrerad anropad bekräftar det unika målet innan det agerar, kräver exakt ett matchande element och växlar aldrig till ett annat fönster eller en anropsbar överordnad. Noll matchningar misslyckas med element_not_found; dubbletter misslyckas med ambiguous_selector. Ett inaktuellt element eller ett återvunnet fönster misslyckas utan att agera. eller inspectsearch och välj en aktuell väljare.
Utan --actionförsöker en filtrerad anropa fortfarande mönstren i ordning på det elementet.
| Action | Operation |
|---|---|
invoke |
InvokePattern.Invoke |
select |
SelectionItemPattern.Select |
toggle |
TogglePattern.Toggle, exakt en gång |
toggle-on / toggle-off |
Läs växlingsläge; lyckas utan att ändra ett redan korrekt tillstånd, annars växla och verifiera |
expand / collapse |
ExpandCollapsePattern.Expand/Collapse |
För toggle-on och toggle-offtillåter ett starttillstånd Indeterminate högst två övergångar och kontrollerar tillståndet efter varje. Andra starttillstånd tillåter en övergång. Om det begärda tillståndet inte har nåtts misslyckas kommandot i stället för att fortsätta växla. En misslyckad verifiering kan lämna kontrollen ändrad. innan ToggleState du bestämmer vad du ska göra härnäst.
Utan --action och utan filter är det automatiska beteendet oförändrat: prova InvokePattern, TogglePattern, SelectionItemPattern och sedan ExpandCollapsePattern (expandera) med ett nytt försök med invokable-ancestor när det behövs.
En åtgärd som inte stöds misslyckas med en icke-nollavslutskod och, med --json, ett strukturerat fel på stderr. Granska den valda kontrollen och välj en åtgärd som den stöder, eller uttryckligen rikta in sig på den avsedda överordnade kontrollen. Lyckad JSON innehåller requestedAction och performedAction; se JSON-referensen.
klicka
Klicka på ett element vid skärmkoordinaterna med hjälp av mussimulering. Använd detta för kontroller som inte stöder InvokePattern (t.ex. kolumnrubriker, listobjekt).
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
Precis som de andra inmatningsverberna
clickförs målet till förgrunden och misslyckas snabbt (no_interactive_desktoppå ett låst/säkert skrivbord,foreground_not_targetom fokus inte kunde överföras) i stället för att klicka på fel fönster. Det löser också elementet på nytt precis före nedknappen: när markören har placerats gör den en sista positionskontroll, så ett kontinuerligt rörligt/animerande mål misslyckas medtarget_movedi stället för att rapportera lyckat resultat efter att klickningen landat på tomt utrymme – en rapporterad framgång innebär att målet fortfarande var på plats när knappen gick ner.
Drag
Tryck på musknappen vid ett tillfälle, flytta till en annan och släpp sedan med drag <from> <to>, där varje slutpunkt antingen är en elementväljare (drar från/till elementets mittpunkt) eller skärmkoordinater x,y exakt som rapporterats av winapp ui inspect. Blanda och matcha fritt (väljare→väljare, väljare→kodord, coords→kodord).
Använder SendInput med mellanliggande rörelser så att appen ser en realistisk ström av WM_MOUSEMOVE meddelanden. Använd den för att ändra ordning på/ändra storlek på handtag, skjutreglage, arbetsyteritning och dra och släpp.
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
Alternativ:
-
--right— Dra med höger musknapp i stället för den vänstra knappen. -
--hold-ms <ms>— Håll ned knappen i början innan du flyttar (standard: 0). Med<from> == <to>(ingen rörelse) utför detta en press-and-hold/long-press gest . -
--dwell-ms <ms>— Bo på målet efter flytten innan du släpper (standard: 0). Låter släppa mål/sammanfoga överlägg som arm från en ihållande hovring (i stället för det ögonblick markören anländer) spärr före knappen upp.
Bare
x,yär skärmkoordinater i samma utrymmesrapportwinapp ui inspect/search, och en väljare matchar elementets centrum – inspektera först för att välja punkter.
Precis som
send-keys --via send-inputinjicerardragOS-wide vid skärmkoordinater efter att målet har förts till förgrunden. Om fokus inte kan föras till målet (t.ex. skydd mot fokusstöld från en bakgrundsprocess ) misslyckas kommandot (foreground_not_target) i stället för att dra i fel fönster – fokusera eller klicka på fönstret först. På ett låst/säkert skrivbord misslyckas det medno_interactive_desktop. Varje elementslutpunkt löses omedelbart före dra. Om den fortfarande flyttar/ändrar storlek (ett animerande mål) misslyckas kommandot medtarget_movedi stället för att dra till en inaktuell punkt. (Barex,yendpoints kan inte verifieras igen, så de används as-is.)
tryck
Mata in syntetiska touchgester med hjälp av API:et Windows pekarinmatning. Kontaktankaret är antingen en elementväljare (använder elementets mittpunkt) eller en explicit skärmkoordinat x,y via --at (samma blankstegsrapporter winapp ui inspect ). Använd den för tryck-/tryckinteraktioner och multi-touch-gester som mussimuleringen inte kan uttrycka.
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)
Alternativ:
-
--gesture <g>—tap(standard),double-tap,long-press,swipe,pinch,stretch. -
--at <x,y>– Explicit startpunkt (skärmkoordinater). Standardvärdet är väljarens elementcenter. -
--to-point <x,y>– Slutpunkt för enswipe. Har företräde framför--direction. -
--direction <right|left|up|down>— Svepriktning (standard:right). Kombinerat med--distanceför att beräkna slutpunkten när--to-pointinte anges. -
--distance <px>— Fingerspridning förpinch/stretch, eller svepavstånd i bildpunkter. -
--hold-ms <ms>— Håll kontakterna nere innan du lyfter (lång hålltid, standardvärdet är 500 ms förlong-pressnär det inte är inställt). -
--duration-ms <ms>— Glida tid för att flytta gester (svep/nypa/sträcka, standard 300). -
--fingers <n>— Antal kontakter (1–10, standard 1).pinch/stretchanvänd alltid 2.
Inmatningssäkerhet.
touchvägrar att mata in om inte ett målfönsterhandtag som inte är noll matchar och det fönstret innehåller förgrunden – det misslyckas medno_targetnär inget fönster kan matchas,foreground_not_targetom fokus inte kunde överföras ellerno_interactive_desktoppå ett låst/säkert skrivbord. Varje koordinat (elementcenter, explicita--at/--to-pointoch genererade waypoints) kontrolleras mot målfönstrets rektangel. En punkt utanför fönstret visas som en varning som inte är dödlig (enwarnings[]post i--json, eller en varningsrad i textläge) och injektionen fortsätter fortfarande – matchar musverb (click/drag/hover/scroll), som också matas in vid koordinater utanför fönstret.--fingersovan 10 avvisas i förväg.Maskinvaruanteckning. Touch föredrar den moderna syntetiska pekarenheten (
CreateSyntheticPointerDevice(PT_TOUCH)) och återgår till det äldreInitializeTouchInjection/InjectTouchInputAPI:et. Om inmatningen inte stöds på den aktuella enheten/sessionen visar kommandot den faktiska Win32-felkoden (t.ex. "stöds inte") i stället för att rapportera en falsk framgång – behandla en icke-noll-utgång som "touch not delivered".Fjärrskrivbord/VM-sessioner. I en Fjärrskrivbord (RDP) eller vissa VM-sessioner kan operativsystemet acceptera syntetisk touch (avslut 0) utan att det faktiskt når målappen. När en fjärrsession identifieras
touchlägger du till en varning om leveransosäkerhet – enwarnings[]post i--jsoneller en varningsrad i textläge. En ✅/exit 0 innebär sedan att inmatningsanropet lyckades, inte att appen tog emot indata; bekräfta effekten medui screenshot/ui inspectnär det är viktigt.
penna
Mata in syntetiska penn-/pennainmatningar – tryckningar och pennstreck – med hjälp av Windows API för syntetisk pekare (CreateSyntheticPointerDevice(PT_PEN); Windows 10 1809+). Rikta in dig på ett elementcenter, en explicit --at punkt eller ett fullständigt --path pennstreck.
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
Alternativ:
-
--at <x,y>— Pennkontaktpunkt (skärmkoordinater). Standardvärdet är väljarens elementcenter. Ignoreras när--pathanges. -
--path "<x,y x,y …>"— Pennstreckssökväg som blankstegsavgränsadex,ypar (en enpunktssökväg är en tryckning). -
--pressure <0.0–1.0>— Penntryck (standard 0,5). -
--tilt-x <deg>/--tilt-y <deg>— Pennlutningsvinklar, −90 till 90 (standard 0). -
--eraser— Använd suddgummidelen i pennan i stället för spetsen. -
--duration-ms <ms>— Total restid för stroke i millisekunder som distribueras som interpolerade UPPDATERINGsramar över sökvägen (standard: ~10 ms per vägpunkt). Använd det här alternativet om du vill styra hur snabbt pennan flyttas från början till slut.
Inmatningssäkerhet. Som
touch,penvägrar att mata in utan ett icke-noll, förgrunds målfönster (no_target/foreground_not_target/no_interactive_desktop) och kontrollerar varje pennanteckningspunkt mot målfönstrets rektangel, som dyker upp någon utomfönsterkoordinat som en icke-dödlig varning (warnings[]i--json, eller en varningsrad i textläge) medan den fortfarande injicerar - överensstämmer med musverberna. Ogiltig--pressure(utanför 0.0–1.0) eller lutning (utanför ±90°) avvisas framifrån.Fjärrskrivbord/VM-sessioner. Pennroutning är särskilt opålitlig över Fjärrskrivbord: inmatningsanropet kan rapportera lyckad (avslut 0) medan inga pennindata når appen. När en fjärrsession identifieras
penlägger till en varning om leveransosäkerhet (warnings[]i--json, eller en varningsrad i textläge) så att en ✅ inte misstas för bekräftad leverans. Verifiera pennberoende flöden på ett lokalt, interaktivt skrivbord.
Hover
Flytta musen till ett elements centrum för att utlösa hovringseffekter (knappbeskrivningar, utfällbara objekt, visuella tillstånd). Använder SendInput för realistisk musrörelse med en liten viggle och väntar sedan på en konfigurerbar uppehållstid.
winapp ui hover btn-info-a1b2 -a myapp # hover with default 800ms dwell
winapp ui hover btn-info-a1b2 -a myapp --dwell-time 1200 # longer dwell for slow tooltips
winapp ui list-windows -a myapp # use the main window's HWND below
winapp ui hover btn-info-a1b2 -a myapp; winapp ui screenshot -w <hwnd> --capture-screen # hover then capture tooltip in place
Alternativ:
-
--dwell-time <ms>— Tid i millisekunder att vänta efter hovring för att effekter ska visas (standard: 800, intervall: 0–1 0000)
send-keys
Skicka syntetiska tangentbordsindata – tangentbordets motsvarighet till click. UIA har inget mönster för tangentbordsinmatning, så detta sjunker till Win32-lagret. Använd den för tangentbordsnavigering (pilar, tabb, Retur, Esc), genvägar (ctrl+c, alt+f4) och skriva in i kontroller som behöver händelser per tangenttryckning i stället set-valueför atomisk skrivning.
winapp ui send-keys "down down enter" -a myapp # arrow navigation then commit
winapp ui send-keys "ctrl+a delete" -a myapp # select all, then delete
winapp ui send-keys "Hello world" --target txt-name-a1b2 -a myapp # focus a field, then type text
winapp ui send-keys "text=down text=down text=enter" -a myapp # type the words, don't press the keys
winapp ui send-keys "down down enter" -a myapp --verbatim # same, but type the whole argument literally
winapp ui send-keys "alt+f4" -a myapp # close window via accelerator
winapp ui send-keys "vk=0x5D" -a myapp # a key with no friendly name (Apps/Menu key)
winapp ui send-keys "ctrl+shift+t" -a myapp --via send-input # use OS-wide injection instead of PostMessage
winapp ui send-keys "win+shift+v" -a myapp --via send-input --allow-system-keys # opt in to drive a global hotkey
winapp ui send-keys "ctrl+capslock+f12" -a myapp --via send-input # Narrator command: toggle developer mode
Nyckel grammatik (blankstegsavgränsade token, offertsträngar för flera token):
-
Namngivna nycklar –
enter/return,tab,esc/escape,space,backspace,delete/del,insert,home,end,pageup/pgup,pagedown/pgdn, ,up/down/left/rightf1–f16,apps,printscreen, .capslock -
Sekvenser – flera token trycks i ordning:
down down enter. -
Kombinationskombinationer för modifierare –
ctrl,shift,alt,winsom är anslutna till+:ctrl+shift+t,alt+f4. En token som börjar med en modifierare men som har ett okänt segment innan den sista (ctrl+a+b) är ett fel. Användtext=eller--verbatimskriv den. -
Skärmläsarkommandon – hold
capslockellerinsert(aliasins), skärmläsaren, NVDA och JAWS-nyckeln:ctrl+capslock+f12växlar skärmläsarens utvecklarläge. Kräver--via send-input, eftersom skärmläsare inte tar emot publicerade nycklar. Om ingen skärmläsare körs aktiverar eller inaktiverar ducapslockCaps Lock och kommandot varnar. Hållinsertkvar för att undvika detta. -
Literal text – alla token som inte är en känd nyckel skrivs tecken efter tecken:
hello. Intilliggande literalord behåller utrymmet mellan dem, så en citerad fras som"Hello world"skrivs ordagrant (utrymmet bevaras); en literal som bara innehåller+somC++ellera+bskrivs som text, inte parsas som en kombination. -
Explicit literal escape – prefixet a token with
text=to type it verbatim even when it collides with a key or modifier name:text=entertypes the word "enter" i stället för att trycka på Retur ochtext=ctrl+askriver literalsträngen. Speglar flyktenvk=; det förrymda värdet förenas fortfarande med intilliggande literalord (text=down low→ "nere lågt"). Eftersom token är blankstegsdelning (och intilliggande literaler återansluts med ett enda blanksteg) använder du omvänt snedstreck i etttext=värde för att skriva blanksteg som annars inte skulle överleva:\s→ blanksteg,\t→ flik,\n→ ny rad,\r→ ny rad,\\→ literal omvänt snedstreck.\n,\r, och var och\r\nen infogar en radbrytning (en Retur /VK_RETURN), såtext=line1\nline2ochtext=line1\r\nline2båda skriver en ny rad. Såtext=a\s\sbskriver "a b" (dubbelt utrymme) ochtext=\shibehåller ett inledande utrymme. En oigenkännlig flykt (t.ex.\x) lämnas ordagrant. -
Helargumentsliteral (
--verbatim) – när hela nyttolasten är literaltext skickar--verbatimdu i stället för att ta bort varje token medtext=. Det skriver argumentet för hela nycklar exakt som det anges – ingen namngiven nyckel/kombination/vk=/text=tolkning – och bevarar, till skillnad från den normala sökvägen, exakta interna blanksteg (ingen komprimering) utan att\sbehöva . Såsend-keys "down down enter" --verbatimskriver orden ochsend-keys "a b" --verbatimbehåller det dubbla utrymmet. Omvänt snedstreck avkodas inte i--verbatimläge (en\sskrivs som ett omvänt snedstreck och ett "s"); använd entext=token när du behöver ett undantaget kontrolltecken. -
Råa virtuella nycklar –
vk=0xNN(hex) ellervk=NN(decimal) för nycklar utan eget namn.
Alternativ:
-
--target <selector>— Fokusera det här elementet (via UIA) innan du skickar nycklar. Utan den går nycklar till appens för närvarande fokuserade element. -
--verbatim— Skriv hela nyckelargumentet som literaltext (ingen nyckel/kombination/vk=/text=parsning) och bevara exakt blanksteg. Hela argumentformen för utrymningen per tokentext=. -
--via <transport>—post-message(standard) publicerarWM_KEYDOWN/WM_KEYUP/WM_CHARi målfönstrets kö. Det är HWND-mål och kringgår UIPI (fungerar över integritetsnivåer).send-inputmatar in hela operativsystemet viaSendInputoch går till förgrundsfönstret.
Välja en transport/kända gränser:
-
post-messageär standard eftersom det kringgår UIPI och inte är beroende av att fönstret är förgrund. Gränser: det kan inte utlösa globala snabbtangenter som registrerats viaWH_KEYBOARD_LLlågnivåkrokar (de trycker på indata uppströms i en fönsterkö) och appar som läser raw-nyckeltillstånd viaGetAsyncKeyStatekanske inte observerar kvarhållna modifierare. Det löser automatiskt och publicerar till måltrådens fokuserade underordnade fönster (viaGetGUIThreadInfo) efter förgrunden, så klassiska Win32/WinForms-appar vars kontroller är separata underordnade fönster tar emot nycklar utan att manuellt rikta kontrollen. WinUI 3/UWP-appar har fönsterlösa XAML-kontroller utan underordnad HWND, så en post harWM_CHAR/WM_KEYDOWNinget att landa i och släpps – efter meddelandet kan inte köra dem (kommandot varnar och avslutar 0); använd .--via send-input(WPF fönster är single-HWND och dirigerar nycklar till det internt fokuserade elementet, så eftermeddelandet fungerar där.) -
send-inputproducerar helt verkliga indata (modifierare som är synliga förGetAsyncKeyState, utlöser lågnivåkrokar) men går till det fönster som är förgrund och blockeras av UIPI när du matar in från en upphöjd process till ett mål med lägre integritet (AppContainer/AppX). Omsend-inputdet rapporterar ett fel är målet sannolikt förhöjt eller en AppX-app – användpost-messageeller kör CLI på matchande integritetsnivå. Som säkerhetsskyddsend-inputverifierar att målfönstret faktiskt är i förgrunden omedelbart innan du matar in och misslyckas (foreground_not_target) i stället för att skriva in i fel fönster om fokus inte kunde tas till det - fokusera eller klicka på fönstret först. På ett låst eller säkert skrivbord misslyckas det i stället medno_interactive_desktop(det finns inget förgrundsfönster att mata in i) – lås upp sessionen eller använd ett UIA-mönsterverb (set-value,invoke). -
Systemreserverade kombinationer (
win+l, ,win+rctrl+shift+esc,ctrl+alt+del,alt+tab,alt+f4,ctrl+esc, ensamwin/printscreen, ...) fungerar på operativsystemet/gränssnittet i stället för bara målet när de skickas till hela operativsystemet.send-inputavvisar dem som standard (fel medinvalid_argumentsoch skickar ingenting) eftersom injicering av dem på OS-nivå har effekter långt utanför målfönstret (t.ex.win+lskulle låsa sessionen). Skicka--allow-system-keysför att välja – detta gör att du kan köra en global snabbtangent som PowerToyswin+shift+vellerwin+r(den globala lågnivåkroken tittar på den OS-breda indataströmmen, så den inmatade kombinationsrutan utlöser den). Undantag som förblir blockerade även med--allow-system-keys:win+llåser arbetsstationen viaLockWorkStation()vilken det inte går att återställa från automatisering (bryter CI- och fjärrskrivbordssessioner) ochctrl+alt+delär en SÄKER uppmärksamhetssekvens (SAS) som Windows droppar från inmatade indata oavsett flagga – den kan aldrig träda i kraft, så den felar (invalid_argumentsavsluta 1) i stället för att rapportera ett missvisande lyckat resultat. Andra kombinationer (alt+f4,ctrl+shift+esc,win+r, ...) tillåts med flaggan – anroparen akta sig. Om du vill leverera en systemkombination till ett visst fönster kan du också använda--via post-message, som är fönsteromfångad och opåverkad (en postadwin+lär ofarlig, även om en postadalt+f4fortfarande stänger målfönstret).
Händelser per tangenttryckning (KeyDown/TextChanged):
-
Namngivna nycklar och modifierarkombinationer (
down,enter,ctrl+shift+t,vk=0xNN) utlöses på riktigtKeyDown(ochKeyUp) på båda transporterna – de levereras som diskretaWM_KEYDOWN/WM_KEYUP(ellerSendInputvirtuella nyckelhändelser). -
Literaltypad text (
hello) skiljer sig efter transport:-
--via send-inputmappar varje tecken till dess virtuella nyckel (plus Skift) på den aktiva tangentbordslayouten, så att målet ser en äktaKeyDownmed rätt virtuell nyckel följt av den OS-sammansattaWM_CHAR(höjaTextChanged) – dvs. en fullständig tangenttryckning per tecken. Tecken som inte kan nås på den aktuella layouten (eller som behöver Ctrl/AltGr) återgår till ett Unicode-paket så att det exakta tecknet fortfarande hamnar. Användsend-inputnär du behöver återgivning per tangenttryckningKeyDown(t.ex. när du kör ett WinUI 3/WPFTextBoxvars hanterare är avstängdaKeyDown). För en normal (icke-upphöjd) WinUI 3-testvärd tar du dess fönster till förgrunden först (winapp ui focus/ klickar på den) sedansend-inputmålet för förgrundsfönstret. -
--via post-messagepublicerar ett enskiltWM_CHARper tecken (det postarWM_KEYDOWN/WM_KEYUPför text som skrivits – de är reserverade för namngivna nycklar/kombinationer), vilket inte genererar ett per teckenKeyDown. Det omdirigeras automatiskt till fönstrets fokuserade underordnade kontroll, så klassiska Win32/WinForms-drivna redigeringskontroller landar texten (höjerWM_CHARTextChanged). Varning: WinUI 3/UWP/XAML-appar (winapps primära mål) har fönsterlösa kontroller som ignorerar postatWM_CHAR/WM_KEYDOWN– så varken literaltext eller namngivna nycklar (Retur, siffror, ...) når dem, även om kommandot rapporterar framgång. Den avger en varning när målet ser ut som XAML och fortfarande avslutar 0 (PostMessageär eld och glöm och kan inte bekräfta leveransen). Använd--via send-inputför att köra WinUI 3/UWP/WPF-appar; reserverapost-messageför klassiska Win32-kontroller eller när du bara behöver det fönsteromfång över integritetsnivåer.
-
JSON-utdata (--json): resultatet är hwnd det effektiva fönster som nycklarna levererades till – för --via post-message det här är den lösta underordnade kontrollen när kommandot omdirigeras till den (inte nödvändigtvis fönstret på den översta nivån-w/-a/-e), så automatiseringen kan bekräfta exakt var indata landade. När det effektiva målet ser ut som en fönsterlös XAML-värd visas även leveransavrådan ovan som en warnings[] post (samma rekommendation som visas i konsolen), så en ✅ avslut 0 misstas inte för bekräftad leverans.
set-value
Ange ett värde för ett redigerbart element programmatiskt (inga tangenttryckningar, ingen appförgrund). Använder en reservkedja:
- ValuePattern – Textbox, ComboBox, PasswordBox och de flesta redigerbara kontroller.
- RangeValuePattern – numeriska kontroller (Skjutreglage, ProgressBar) när värdet parsas som ett tal.
-
LegacyIAccessible (
IAccessible::put_accValue) – återställningen för redigeringskontroller med endast TextPattern som inte exponerar något ValuePattern (t.ex. rich-edit/Documentcompose-rutor). Detta stänger läs-/skrivgapet därget-valueen sådan kontroll kan läsas, menset-valuedet gick inte.
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
Om inget av de tre mönstren kan ange värdet misslyckas set-value med ett tydligt fel som pekar på send-keys som den sista utvägen.
Alla rich-redigerare stöder inte programmatiska uppsättningar. LegacyIAccessible-återställningen fungerar bara på kontroller vars tillgänglighet implementerar
IAccessible::put_accValue– inbyggda Win32 rich-edit-kontroller och Chromium/Electron/WebView2 består av ytor som vanligtvis gör det. WinUI 3RichEditBoxoch WPFRichTextBoxstöder inte programmatisk värdeinställning – genom design exponerar de innehållet för UI Automation som skrivskyddat (textmönster, inget värdemönster som kan anges), såset-valuede kan inte skriva till dem. Användsend-keys(som behöver ett olåst, förgrundskrivbord) för dem.
get-value
Läs det aktuella värdet från ett element. Använder en smart återställningskedja: TextPattern (RichEditBox, Document) → ValuePattern (TextBox, Slider) → SelectionPattern (ComboBox, RadioButton, TabView) → Name (labels).
winapp ui get-value doc-texteditor-53ad -a notepad # read full document text
winapp ui get-value SearchBox -a myapp # read TextBox content
winapp ui get-value CmbTheme -a myapp # read ComboBox selected item
winapp ui get-value sld-volume-b2c3 -a myapp # read Slider value
winapp ui get-value lbl-title-a1b2 -a myapp --json # JSON: { "elementId": "...", "text": "..." }
winapp ui get-value SearchBox -a myapp --json
winapp ui wait-for SearchBox -a myapp --value "" --timeout 5000
Ett tomt textfält med läsbehörighet returnerar "text": "", inte dess hjälpmedelsetikett. Endast blankstegsinnehåll bevaras också i JSON.
wait-for --value "" matchar ett tomt fält, oavsett om det är nytt eller har rensats efter redigering. Om du vill läsa hjälpmedelsetiketten i stället använder du get-property --property Name.
focus
winapp ui focus txt-textbox-a4b1 -a notepad
Aktiverar den valda kontrollens fönster när det behövs och fokuserar sedan kontrollen.
Väljaren krävs. -w <HWND> eller -a <app> för att välja målet.
Lyckat innebär att fönstret var förgrundsfönster och att den valda kontrollen bekräftades HasKeyboardFocus innan kommandot returnerades. Kommandot tillåter upp till 500 ms för kontrollen att rapportera fokus; det stoppas om målet försvinner eller förlorar förgrunden i stället för att försöka ta fokus tillbaka. Det räcker inte med en ägd dialogruta framför huvudfönstret: välj en kontroll i dialogrutan om det är målet.
Det här kommandot behöver ett olåst, interaktivt skrivbord och kringgår inte Windows aktiveringsbegränsningar. Om det misslyckas med foreground_not_targetaktiverar du det avsedda fönstret manuellt och söker efter en blockeringsdialogruta innan du försöker igen.
För focus_not_acquiredkontrollerar du det aktuella användargränssnittet och väljer en fokuserbar kontroll.
För stale_elementkan du återupptäcka målet med inspect eller search.
Behåll samma --on mål för identifierings- och återförsökskommandon.
bläddra till vyn
Rulla ett element till det synliga området.
winapp ui scroll-into-view itm-targetitem-c3d4 -a myapp
vänta på
Vänta tills ett element visas, försvinner eller har ett värde som når ett mål.
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
Bläddra
Rulla ett containerelement. Hitta rullningsbara containrar med search scroll – leta [scroll:v] efter (lodräta) eller [scroll:h] (vågräta) markörer.
# 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
Alternativ:
-
--direction <up|down|left|right>– Rulla inkrementellt viaScrollPattern. -
--to <top|bottom>– Hoppa till start/slut viaScrollPattern. -
--wheel <notches>— Syntetisera mushjulets indata över elementets mitt viaSendInput, i hjulskåror (detenter):1= en skåra upp/bort,-1= ett snäpp ner/mot,3= tre skåror uppåt. (Varje hack är WindowsWHEEL_DELTAav 120 enheter somSendInputförbrukar; CLI skalar skåror med 120 åt dig.) KringgårScrollPattern.
--direction,--to, och--wheelär ömsesidigt uteslutande – passera exakt en. Eftersom--wheelindata för hela operativsystemet matas in vid skärmkoordinater förs målet först till förgrunden och misslyckas (foreground_not_target) om fokus inte kunde överföras, i stället för att rulla fel fönster.
get-focused
winapp ui get-focused -a myapp
winapp ui get-focused -w <HWND> --json
Visa elementet som för närvarande har tangentbordsfokus i den valda appen, inklusive kontroller vars appägarskap endast är tillgängligt via det överordnade fönstret.
Med -wmåste fokus tillhöra det fönstret, inte ett annat fönster eller ett ägt popup-fönster i samma process. Med -aingår andra fönster i den valda processen.
JSON-utdata har hasFocus:false när inget fokuserat element kan verifieras som tillhörande målet. Om en fokus- eller fönsterägarfråga misslyckas avslutar kommandot nonzero i stället. försök get-focusedigen och återupptäck fönstret med list-windows om det har stängts.
list-windows
Visa en lista över alla synliga fönster för en app, inklusive popup-fönster och dialogrutor. Som standard utesluts namnlösta fönster med nollstorlek (osynliga systemfönster).
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
avkastning
Släpp arbetsflödets användargränssnitt tidigt i stället för att vänta ut den fyra sekunder långa inaktiva respiten. Kräver WINAPP_UI_WORKFLOW_ID; tar ingen app och ingen väljare. Se Släppa svängen tidigt.
winapp ui yield
winapp ui yield --json # {"released": true} — or false when nothing was held
Ramverksstöd
| Ramverk | Inspektera | search | Åberopa | set-value | skärmbild |
|---|---|---|---|---|---|
| WPF | ✅ Fullständigt träd | ✅ Alla egenskaper | ✅ Alla mönster | ✅ ¹ | ✅ |
| WinForms (på engelska) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Win32 | ✅ | ✅ | ✅ | ✅ | ✅ |
| WinUI 3 | ✅ | ✅ | ✅ | ✅ ¹ | ✅ |
| Elektron | ⚠️ Kromträd | ⚠️ Begränsad | ⚠️ Varierar | ⚠️ Varierar | ✅ |
| Flutter | ⚠️ Grundläggande | ⚠️ Grundläggande | ❌ Minimalt | ❌ | ✅ |
¹ set-value fungerar på alla kontroller som exponerar ValuePattern/RangeValuePattern, plus redigeringskontroller med endast TextPattern vars hjälpmedel implementeras IAccessible::put_accValue (LegacyIAccessible-återställning).
WinUI 3 RichEditBox och WPF RichTextBox är undantag – de exponerar endast det skrivskyddade textmönstret (inget värdemönster som kan anges), så att de inte kan ställas in programmatiskt genom design. Använd send-keys (interaktivt skrivbord krävs) för att skriva in dem.
Använda motorn från din egen kod
Allt winapp ui är tillgängligt som ett bibliotek, så du kan köra samma automatisering från ett test eller verktyg utan att utskalning till CLI:
| Package | Vad som läggs till |
|---|---|
Microsoft.Windows.SDK.BuildTools.WinApp.UIAutomation |
Inspektion, väljare, UIA-mönsterinteraktion, inmatning, skärmbilder |
Microsoft.Windows.SDK.BuildTools.WinApp.UIAutomation.Recording |
Videoinspelning till MP4, plus rampaket |
var services = new ServiceCollection().AddLogging().AddWinAppUiAutomation().BuildServiceProvider();
var ui = services.GetRequiredService<IUiAutomation>();
var target = UiTarget.FromWindowHandle(myWindowHandle);
var save = await ui.FindSingleElementAsync(target, new UiSelector { Query = "Save" }, default);
await ui.InvokeAsync(target, save!, default);
För deterministiska åtgärder använder du överlagringen :UiInvokeAction
var selected = await ui.FindSingleElementAsync(
target, new UiSelector { Query = "Save" }, requireUnique: true, default);
if (selected is null) throw new InvalidOperationException("Save was not found.");
UiInvokeActionResult result = await ui.InvokeAsync(target, selected, UiInvokeAction.Invoke, default);
requireUnique: true avvisar tvetydig text i stället för att välja en anropsbar matchning. Exakta AutomationId-matchningar har företräde framför namn eller AutomationId-understrängar. ett unikt namn kan fortfarande välja en kontroll vars AutomationId delas.
För ett appomfångsbegränsat mål omfattar kontrollen alla dess app-/ägda fönster. Använd -w <HWND> (eller ett explicit biblioteksmål) för att begränsa urvalsomfånget.
Den returnerar Pattern och PerformedAction med samma betydelse som CLI-åtgärdsresultatet.
Skicka ett element som returneras av inspektion eller val, med dess runtime-snigel eller unika AutomationId intakt. Explicita åtgärder avvisar en saknad eller tvetydig identitet i stället för att binda om efter namn och kontrolltyp.
För begränsade läsningar anger du UiSelector.Root till en annan UiSelector, ControlType till ett typnamn och ClassName till literalproviderklassen. Dessa använder samma frågepredikat som CLI. Endast en rotnivå stöds: selector.Root.Root måste vara null. En kapslad rot kastar ArgumentException innan du letar upp målfönstret. Använd ett unikt rot-AutomationId eller en snigel i stället för att kapsla rotväljare.
UiControlTypes.GetId(name) löser officiella typnamn och de två dokumenterade aliasen som returneras 0 för ett ogiltigt namn.
UiControlTypes.GetName(id) returnerar det kanoniska namnet eller Unknown(id) för ett okänt ID.
När du skickar en UiElement återställd från JSON till GetTextAsync eller GetPropertiesAsyncbehåller du dess Selector och WindowHandle. En snigelväljare måste fortfarande identifiera det ursprungliga elementet. Om den inte längre finns genererar UiElementNotFoundException dessa läsningar i stället för att välja ett annat element med samma AutomationId eller namn. Kör den ursprungliga frågan igen för att uppdatera resultatet. Begränsade läsningar sprider också fel från allmänna UIA-egenskapsmottagare och förvärvade UIA-mönster i stället för att returnera null eller ett tidigare insamlat värde.
Inspelning är ett separat paket så att projekt som endast inspekterar och kör användargränssnittet inte drar in SkiaSharp. Automation-paketet riktar in sig på både net10.0-windows och net10.0-windows10.0.19041.0; det senare lägger till Windows Graphics Capture, vilket är det som gör att du kan screenshot avbilda occluded eller GPU-sammansatta windows. Se varje pakets README på NuGet för det fullständiga API:et och kompromissen för målramverket.
UiTarget.FromWindowHandle är startpunkten för testramverk som redan ger dig ett fönster , till exempel MSTest.Windows.UIAutomation, vars WindowTest.MainWindow är en UIA2 AutomationElement som du brygger över med MainWindow.Current.NativeWindowHandle.
Felsökning
| Error | Orsak | Lösning |
|---|---|---|
| "Ingen app som körs hittades" | Appen körs inte eller namnmatchningsfel | Kontrollera processnamnet eller använd PID |
| "Flera fönster matchar" | Tvetydigt -a värde |
Använd -w <HWND> från de angivna alternativen |
| "har flera fönster" | Processen har flera fönster | Använd -w <HWND> för att rikta in dig på en specifik |
| "Väljaren matchade N-element" | Tvetydig äldre väljare | Använda sniglar från inspect utdata eller lägg till [0]i [1] äldre väljare |
| "Elementet kan ha ändrats" | Snigelhash matchar inte aktuellt element |
inspect Kör igen eller search för att få nya sniglar |
| "stöder inte något anropsmönster" | Det går inte att anropa elementet | Använd inspect på -elementet för att hitta ett anropsbart underordnat objekt |
| "Inget UIA-fönster hittades" | UIA kan inte se processen | Använd list-windows för att hitta HWND och sedan -w |
| "Fönstret har noll storlek" | Fönstret minimeras | Appen återställs automatiskt |
| Popup-/listruta finns inte i skärmbilden | Standardinsamlingen är per fönster och innehåller inte obevakade överlägg | Följ arbetsflödet för skärmbildöverlägg för att välja ett fönster med -w <hwnd> --capture-screen |
foreground_not_target från --capture-screen |
Windows vägrade aktiveringen, så en skärmdump skulle ha spelat in vilket fönster som faktiskt finns framför | Klicka på målfönstret eller stäng fönstret för fokusstöld och försök igen eller släpp --capture-screen |
element_not_found under posten |
Angiven väljare men inget matchande element |
inspect Kör igen eller search för att hämta en ny väljare |
| WGC är inte tillgängligt under posten | WGC-infångnings-init misslyckades. ingen tyst reserv | Kontrollera GPU/drivrutin; använda --capture-screen för att samtycka till screen-DC-avbildning |
Vanliga mönster
Navigera och verifiera
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
Hitta text och anropa dess överordnade
# 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
Tvetydiga duplicerade element
winapp ui search '#Image' -a myapp; winapp ui invoke itm-image-a2b3 -a myapp
Skärmbild med popup-överlägg
winapp ui list-windows -a myapp # use the main window's HWND below
winapp ui set-value txt-searchbox-e5f6 "query" -a myapp; winapp ui screenshot -w <hwnd> --capture-screen
Navigera, vänta och verifiera (enkel kedja)
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
Identifiera, klicka och verifiera
winapp ui inspect -a myapp --interactive; winapp ui invoke btn-submit-7a90 -a myapp; winapp ui screenshot -a myapp
Interaktion med fildialogruta
Dialogrutan Öppna/spara filer är standarddialogrutor för Windows med UIA-stöd:
# 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>
Använd inspect -w <dialog-hwnd> --interactive för att identifiera de faktiska sniglarna för en specifik dialogruta.
Varför ; för länkning (inte &&)
PowerShell-operatorn kan låsas && när ett inbyggt CLI skriver till stderr eller använder ANSI-escape-sekvenser. Använd ; i stället – det kör varje kommando villkorslöst och undviker det här dödläget. Det här är också bättre för agentarbetsflöden: du vill vanligtvis att skärmbilden ska köras även om anropan hade en avslut som inte var noll.
CI-testmönster
Använd winapp ui-kommandon i CI-pipelines (GitHub Actions, Azure DevOps) för röktester och UI-validering.
wait-for med --property och --value fungerar som ett intyg – det returnerar slutkod 1 vid timeout, misslyckas CI-steget automatiskt.
Starta och testa i 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-elementtillstånd med wait-for
wait-for --value avsöker tills ett elements värde matchar den förväntade strängen med samma smarta återställning som get-value (TextPattern → ValuePattern → SelectionPattern → Name). Returnerar slutkod 0 vid matchning, slutkod 1 vid timeout – vilket gör den till en CI-vänlig försäkran. Använd --property för att kontrollera en specifik UIA-egenskap i stället.
# 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
Bekräfta med JSON-utdata
Använd --json med PowerShell eller jq för mer komplexa kontroller:
Slutkodskontrakt för
searchochwait-fori--jsonläge: när inget element matchar (search) eller väntetiden överskrider tidsgränsen (wait-for), skriver kommandot ett fullständigt parsbart resultatkuvert till stdout ({ "matchCount": 0, ... }eller{ "found": false, "timedOut": true, ... }) och returnerar slutkod 1. Stderr är tomt i--jsonläget (loggningsutdata ignoreras). Gren på kuvertfälten, eller på$LASTEXITCODE, beroende på vilken som är mer ergonomisk.
# Assert: search found exactly one match
$result = winapp ui search "Submit" -a $pid --json | ConvertFrom-Json
if ($result.matchCount -ne 1) { throw "Expected 1 Submit button, found $($result.matchCount)" }
# Assert: element has expected properties
# inspect --json returns { windows: [{ hwnd, title, elements: [...] }] };
# each window's elements[] is the nested tree (children rendered via .children).
$tree = winapp ui inspect "Counter Display" -a $pid --json | ConvertFrom-Json
$counter = $tree.windows[0].elements[0]
if ($counter.name -ne "Count: 3") { throw "Counter value wrong: $($counter.name)" }
# Read typed element state while preserving the legacy string property map
$property = winapp ui get-property "Counter Display" -a $pid --json | ConvertFrom-Json
if ($property.element.type -ne "Text") { throw "Unexpected type: $($property.element.type)" }
if ($property.element.isOffscreen) { throw "Counter is offscreen" }
JSON-kuverten är:
-
inspect:{ "depth", "interactive", "hideDisabled", "hideOffscreen", "windows": [...] } -
search:{ "matchCount", "hasMore", "matches": [...] } -
wait-for:{ "found", "waitedMs", "element"?, "timedOut" } -
get-property:{ "elementId", "element", "properties": { ... } }
Inskrivna element använder type och numeriska x, y, widthoch height.
Geometri finns i fysiska skärmpixlar.
0,0,0,0är UI Automation tomma/no-displayed-UI-rektangel i den här projektionen; isOffscreen är separat, så ett offscreen-element kan fortfarande ha icke-zero-gränser.
Varje inspect --jsonwindows[] post och resultatet status --json inkluderar windowDpi, scale (windowDpi / 96), dpiAwarenessoch coordinateSpace: "physical-screen-pixels". Dessa beskriver målfönstrets DPI-kontext, inte ovillkorlig övervakning av DPI: Windows rapporterar 96 för ett omedvetet fönster, system-DPI för ett systemmedvetent fönster och aktuell övervaknings-DPI för ett fönster som är medvetet per övervakare. Om HWND- eller DPI-kontexten inte kan läsas misslyckas kommandot i stället för att tyst ersätta 96. När status löser en process innan den har ett fönster på den översta nivån, hwnd är 0 och DPI-fält utelämnas tills ett fönster finns. För hela processen inspectförblir det valda målfönstret felsnabbt. Om ett senare popup-fönster försvinner efter att dess träd har lästs bär posten windows[] och utelämnar dpiError DPI-fälten medan de återstående fönsterträden fortfarande returneras.
Se de levererade winapp-ui-automation färdigheterna references/ui-json-envelope.md för fullständiga exempel på varje kuvert.
Exempel på fullständigt röktest
# 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