Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Überprüfen und interagieren Sie mit der Ausführung von Windows Anwendungen über die Befehlszeile. Wird von KI-Agents und Entwicklern für Benutzeroberflächentests, Debugging und Automatisierung verwendet.
Übersicht
winapp ui bietet Befehle zum Überprüfen und Interagieren mit Windows App-UIs.
Verwendet Windows Benutzeroberflächenautomatisierung (UIA). Funktioniert mit jeder Windows-App – WPF, WinForms, Win32, Electron und WinUI 3.
Die meisten Befehle steuern die App über UIA-Muster (keine Eingabeeinfügung). Die Ausnahmen fügen echte Eingaben ein: ui click/ui hover/ui dragVerwenden sie Maussimulation,ui touch/ui pen Synthetisieren von Toucheingaben und Stift-/Eingabestift und ui send-keys synthetisiert Tastatureingaben – für Steuerelemente und Szenarien, die UIA-Muster nicht steuern können.
Important
Interactive-Desktop-Anforderung (Eingabeinjizierverben).click, hover, , dragtouch, pen, scroll --wheelund send-keys --via send-input synthetisieren Eingabe auf Betriebssystemebene, sodass sie einen entsperrten, interaktiven Desktop mit dem Zielfenster im Vordergrund benötigen. Auf einer gesperrten Arbeitsstation oder einem sicheren Desktop (LogonUI/UAC) können sie nicht injizieren und schlagen schnell fehl no_interactive_desktop (anders als die Rechte/foreground_not_target Fälle).
touch
/
pen wenn kein Fenster aufgelöst wird (no_target); eine Koordinate außerhalb des Zielfensters ist eine nicht tödliche Warnung (ein warnings[] Eintrag unter --jsonoder eine Warnzeile im Textmodus), und das Einfügen wird weiterhin fortgesetzt – konsistent mit den Mausverben. Alles andere – inspect, , , searchget-property, get-value, set-valuewait-for, , invoke, – scroll --direction/--to steuert die App über UIA-Muster und ist headless/locked-session freundlich.
screenshot ist die Ausnahme zwischen den nicht injizierten Verben: Sie benötigt eine exklusive Drehung, und die Aufnahme kann einen verwendbaren interaktiven Desktop benötigen, da das Modul ein minimiertes Ziel wiederhergestellt und zurück in den Vordergrund fällt, wenn die Frameerfassung nicht verfügbar oder --capture-screen verwendet wird. Bevorzugen Sie die UIA-Musterverben in CI; reserve the injection verbs for scenarios that genuinely need real input. Vor dem Einfügen lösen die Gestenverben auch das Zielelement erneut auf und lehnen target_moved sie ab, wenn sie immer noch animieren/verschieben, anstatt Eingaben im leeren Raum zu landen.
Quick Start
Führen Sie winapp ui --help die Ausführung für die Kernschleife aus: inspect -a <app> --interactive Um zu sehen, invokeset-value worauf Sie reagieren oder handeln können, und get-value um das Ergebnis zu überprüfen. Beispiele für --help jeden Befehl. Ein unbekannter Befehl, z winapp ui dump. B. wird mit Code 1 beendet und schlägt die nächstgelegenen Befehle vor (als JSON-Fehler bei suggestions der Übergabe --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
Ausführen der Benutzeroberflächenautomatisierung in Windows Sandbox
Um die Automatisierung auf Dem Desktop zu beschränken, fügen Sie --on sandbox den Befehlen "Ausführen" und "Ui" hinzu:
winapp run . --on sandbox --detach
winapp ui inspect --on sandbox -a MyApp
winapp ui invoke --on sandbox SubmitButton -a MyApp
--detach gibt nach dem Start zurück; ohne sie wartet, run bis die App beendet wird. Behalten Sie --on sandbox alle Gastbefehle bei, einschließlich derjenigen, die eine PID oder ein Fensterhandle verwenden.
Siehe Windows Sandkastenausführung für Clientanforderungen, kurze Setup-/erneute Verbindung von Fokusänderungen, Workflowkoordination und Hostausgabeübermittlung.
Bereichsbezogene und eingegebene Abfragen
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
Diese Befehle akzeptieren optionale Filter für die Elementauswahl: inspect (mit einer Auswahl), search, , get-property, , get-value, , wait-forinvoke, set-value, click, scroll-into-viewhoverfocusscreenshotrecordscrolltouchund .pen
drag (zwei Selektoren) und send-keys --target nicht.
Der Selektor und jeder bereitgestellte Filter muss mit demselben Element übereinstimmen. Filter schränken eine Auswahl ein, also inspect, screenshotund record, deren Selektor optional ist, schlagen bei invalid_arguments gegebenen Filtern ohne einen Fehler fehl. Für touch und pen, Filter benötigen eine Auswahl; sie können nicht mit --at oder --path (invalid_arguments) kombiniert werden:
-
--root <selector>durchsucht nur Nachfolger eines eindeutig übereinstimmenden Stamms, niemals den Stamm selbst. Verwenden Sie eine AutomationId oder einen Schrägstrichinspect, um mehrdeutig zu sein. Ein Stamm, der mehreren Elementen entspricht, schlägt fehlambiguous_selector, auch wenn eine Übereinstimmung einsehbar ist. Ein fehlender Stamm erzeugt keine Übereinstimmungen. Sobald der Stamm gefunden wurde, durchsuchen Abfragen keine nicht verknüpften Popupfenster, auch wenn keine untergeordneten Übereinstimmungen vorhanden sind. Abfragen sind nicht durchinspectdie Anzeigetiefe beschränkt. -
--type <control-type>entspricht einem UIA-Steuerelementtyp, wobei die Groß-/Kleinschreibung ignoriert wird. Die einzigen Aliase sindTextBox→EditundTextBlock→Text. Unbekannte Namen (einschließlich numerischer IDs und Wildcardausdrücke) schlagen mitinvalid_arguments. -
--class-name <literal>entspricht der gesamten UIAClassNamedes Anbieters, wobei der Fall ignoriert wird. Es handelt sich nicht um eine Teilzeichenfolge, einen Wildcard- oder regulären Ausdruck. Wirdget-property --property ClassNameverwendet, um den Wert des Anbieters zu ermitteln. Der Klassenname muss nicht dem UIA-Steuerelementtyp entsprechen.
Gefilterte Abfragen verwenden die Steuerelementansicht von UIA, die gleiche Ansicht, die von inspect.
Anbieterknoten, die nur in der unformatierten Ansicht verfügbar gemacht werden, werden nicht zurückgegeben. wird inspect verwendet, um das enthaltende Steuerelement und dessen Selektor zu finden.
Alle 41 offiziellen Typen werden unterstützt: Button, , Calendar, CheckBox, ComboBox, Edit, Hyperlink, ListItemHeaderHeaderItemTableMenuBarMenuListImageTreeTreeItemCustomToolTipGroupTextWindowTabItemPaneDocumentMenuItemProgressBarScrollBarSpinnerTabSliderStatusBarRadioButtonDataItemDataGridSplitButtonToolBarThumb, TitleBar. . SeparatorSemanticZoomAppBar
wait-for löst die Stammmarkierer bei jeder Abfrage erneut auf, sodass der Stamm nach dem Start des Befehls angezeigt werden kann. Mit --gone, ein nicht vorhandener Stamm bedeutet, dass es keinen übereinstimmenden Untergeordneten gibt. Ein mehrdeutiger Stamm ist ein Fehler, nicht erfolgreich.
Ein unterbrochener Nachschlagevorgang ist kein Beweis für das Verschwinden: Wenn ein Element während der Suche entfernt oder vor einem --value Lesen ersetzt wird, überprüft die nächste Abfrage erneut. Andere Nachschlage- oder Lesefehler schlagen den Befehl fehl.
-w <HWND> Beschränkt die Stammermittlung auf die UIA-Struktur dieses Fensters. Mit -adieser Funktion kann die Stammermittlung auch die Popupfenster der App finden. Exakte Automatisierungs-ID-Übereinstimmungen haben Vorrang vor Teilzeichenfolgenüberstimmungen über alle diese Fenster; Mehrere genaue Übereinstimmungen schlagen immer noch mit ambiguous_selector.
Eine Stammschräge wählt dieses Element auch dann aus, wenn ein anderes Fenster dieselbe AutomationId aufweist. Wenn der ausgewählte Stamm ersetzt wird, stimmt der alte Strich nicht mehr überein; verwenden Sie eine AutomationId oder einen Namenstamm, wenn Sie abfragen möchten, um einem Ersatz zu folgen.
Wenn Filter vorhanden sind, schlägt jeder Befehl außer search fehl, wenn mehr als ein Element verbleibt ambiguous_selector . Schränken Sie die Filter ein, oder verwenden Sie einen eindeutigen Strich. Befehle, die auf die Elementanzahl reagieren, entsprechen in jedem fenster, in dem sie suchen, sodass ein übereinstimmende Steuerelement in einem eigenen Dialogfeld auch die Auswahl mehrdeutig macht. Exakte AutomationId-Übereinstimmungen behalten Vorrang vor Teilzeichenfolgenüberstimmungen innerhalb des gefilterten Bereichs. Beim Weglassen aller drei Optionen bleibt das vorhandene Abfrageverhalten erhalten.
Koordinieren gleichzeitiger Benutzeroberflächenworkflows
Windows verfügt nur über ein Vordergrundfenster, einen Tastaturfokus, einen Cursor und einen Eingabedatenstrom. Wenn zwei winapp ui Workflows auf demselben angemeldeten Desktop gleichzeitig ausgeführt werden, können sie den Fokus gegenseitig stehlen, ein Gerade geöffnetes Menü schließen oder ein Ziel unter einem ausstehenden Klick heraus verschieben.
Schiedsverfahren ist immer aktiviert. Jeder winapp ui Befehl, der den physischen Desktop berührt, wechselt ohne Setup und keine Möglichkeit, ihn zu deaktivieren, sodass zwei Agents niemals in die Fenster des anderen eingeben können. Schreibgeschützte Befehle werden gleichzeitig ausgeführt. Die einzige Ausnahme ist ein Prozess, der nicht auf den Koordinationsordner von winapp zugreifen kann, z. B. eine Agent-Sandbox, die blockiert %USERPROFILE%\.winapp: ihre Befehle werden weiterhin ausgeführt, aber ohne Sichten zu wechseln und eine Warnung (außer mit --json oder --quiet) zu drucken.
Die Kontinuität zwischen Befehlen ist opt-in. Standardmäßig ist jeder Befehl ein eigenständiger Einschuss: Er wartet seine Drehung, erledigt seine Arbeit und gibt den Desktop sofort frei. Um den Desktop über mehrere Befehle hinweg zu halten, weisen Sie ihnen alle die gleiche Workflow-ID zu:
# Set once per logical UI workflow
$env:WINAPP_UI_WORKFLOW_ID = [guid]::NewGuid().ToString()
Was Sie wissen müssen:
- Eine Workflow-ID benennt einen logischen Workflow – nicht unbedingt einen ganzen Agent und nicht unbedingt eine App. Verwenden Sie denselben Wert für die Zusammenarbeit von Befehlen (eine Aufzeichnung plus die Klicks, die erfasst werden sollen); Verwenden Sie unterschiedliche Werte für unabhängige Workflows, auch wenn ein Agent beide startet.
- Ohne ID ist jeder Befehl ein unabhängiger Einschuss. Es wird immer noch willkürlich, aber es bankiert keine Gnade und übergibt den Desktop aus dem Moment, in dem es beendet ist. Zwei no-id Befehle sind separate Workflows, auch wenn sie von derselben Shell gestartet werden.
- Fresh-Shell und adaptive Hosts müssen denselben Wert einfügen. Wenn jeder Befehl in einer neuen Shell ausgeführt wird – also wie die meisten Agenttoolaufrufe funktionieren – ist das einzige, was sie gruppieren kann, ist ein expliziter
WINAPP_UI_WORKFLOW_IDÜbergeben an jeden kooperierenden Aufruf. - Die Vier-Sekunden-Gnade schützt enge Brüche und keine Modellgrundsätze. Ein Workflow mit einer ID behält seine Drehung bei, solange der nächste Befehl innerhalb von vier Sekunden beginnt. Dies deckt Back-to-Back-Befehle in einem Skript ab; es läuft absichtlich ab, während ein Modell denkt. Es ist ein Fallback für den Fallback, wenn Sie nicht sagen können, dass Sie fertig sind – wenn Sie können, statt
winapp ui yielddarauf zu warten. - Adaptive Workflows müssen erneut abrufen, realidate und wiedergeben. Nach einer Begründungslücke hat möglicherweise ein anderer Workflow den Desktop verwendet. Öffnen Sie daher das Menü erneut, lösen Sie das Element erneut auf, und handeln Sie dann. Senden Sie bekannte End-to-End-Sequenzen als ein enges Skript, anstatt den Desktop zu halten, während Sie denken.
- Die Sortierung ist zuerst die Besitzeraffinität, dann FIFO unter den anderen. Während ein Workflow aktiv oder innerhalb seiner Gnade ist, kann er befehle ausstellen, auch wenn andere Workflows bereits warten. Sobald sie ausgeführt
winapp ui yieldwird oder die Gnade abläuft, werden wartende Workflows in strenger Ankunftsreihenfolge bedient. Kontinuierliche Aktivität nach einem Workflow kann daher andere auf unbestimmte Zeit verzögern. - Es gibt keine harte Kappe. Ein langes Skript, eine ungebundene Aufzeichnung oder eine Fehlerschleife können andere Stummschaltungsworkflows blockieren.
-
Abbruch oder Beendigung des Prozesses ist die Wiederherstellung für einen hängen gebliebenen Liveworkflow. Wartende Befehle drucken einen Status nach einer Sekunde und können mit
Ctrl+Cbeendet werden, was beendet130wird. - Nur kompatible aktualisierte Binärdateien arbeiten zusammen. Ältere
winappBuilds predate dieses Feature und werden nicht koordiniert. Code, der die Benutzeroberflächenautomatisierung NuGet-Pakete direkt aufruft, liegt außerhalb dieser Garantie vollständig – Koordination lebt in der CLI, nicht in den Paketen.
Welche Befehle auf eine Drehung warten:
| Behavior | Commands |
|---|---|
| Wird gleichzeitig ausgeführt (wartet niemals) |
status, list-windows, inspect, search, , get-property, get-value, get-focused, wait-for |
| Wartet auf die Drehung, nimmt aber nie den Desktop |
set-value, , scroll-into-viewscroll --direction/--torecord |
| Wartet auf die Drehung und nimmt den Desktop exklusiv an |
invoke, click, , hoverdrag, scroll --wheel, touch, pen, , , focus, , send-keysscreenshot |
Die mittlere Zeile ist der wert zu verstehen.
set-valueund scroll-into-view steuern UIA-Muster--toscroll --direction/anstelle des Vordergrunds, sodass sie kopflos/gesperrt bleiben und niemals verhindern, dass jemand den Desktop verwendet. Sie ändern jedoch , was die App anzeigt, sodass sie hinter der Wendung eines anderen Workflows warten, anstatt ein Feld zu bearbeiten oder eine Liste aus dem Klick einer anderen Person heraus zu scrollen.
Innerhalb eines Workflows überlappen sie sich mit anderen freigegebenen Arbeiten – also, wie eine record Aufzeichnung der set-value Anrufe erfasst. Sie ignorieren die Vorwärtsbarriere ihres eigenen Workflows nicht: Ein früherer DesktopExclusive Befehl desselben Workflows (a click, a screenshot) blockiert sie immer noch, genau wie er jeden späteren Befehl blockiert, also ein Klick und die Mutation, die darauf folgt, in der Reihenfolge, in der Sie sie geschrieben haben.
screenshot immer warteschlangen für eine exklusive Drehung. Nicht jede Aufnahme stört den Desktop – ein normales sichtbares Fenster, das über Windows Grafikaufnahme erfasst wird, nicht - aber das Modul stellt das Ziel wieder her, wenn es minimiert ist, und fällt zurück in den Vordergrund, wenn die Frameaufnahme nicht verfügbar ist oder --capture-screen den Livebildschirm liest. Diese benötigen nur eine Oberfläche, wenn die Aufnahme läuft, sodass der Befehl die Drehung vornimmt, anstatt zu erraten. Wenn es mehrere Fenster zusammenfasst, erfasst es sie alle unter einer exklusiven Drehung, sodass das gespeicherte Bild ein einziger konsistenter Moment und nicht eine Mischung aus Vor- und Nachher ist. Die Codierung und das Schreiben der Datei erfolgt nach der Veröffentlichung des Desktops.
--capture-screenbenötigt genau ein Fenster. Die Aufzeichnung des Livebildschirms zeichnet alles, was sich tatsächlich im Vordergrund befindet, auf, und nur ein Fenster kann sein. Wenn Sie ein Fenster explizit auswählen,-w <hwnd>erhalten Sie genau einen Bereich – die Pixel innerhalb der Grenzen dieses Fensters, einschließlich eines dialogfelds oder überlagern sie sichtbar darüber, was der Grund ist, den Bildschirm an erster Stelle zu lesen. Wenn-aeine Übereinstimmung mit mehreren Fenstern auf oberster Ebene oder im Besitz besteht, gibt es keine solche Auswahl, sodass der Befehl fehlschlägtinvalid_arguments, bevor etwas erfasst wird, anstatt den Vordergrund zu bekämpfen. Führen Sie das Ausführen aus, und versuchen Siewinapp ui list-windows -a <app>es erneut-w <hwnd>, oder legen--capture-screenSie es ab, um jedes Fenster aus seinem eigenen Inhalt zu zusammengesetzt.
record teilt seine Drehung, sodass die Eingabe mit demselben Workflow mit der Erfassung interleave kann – d. h., wie Sie einen Workflow aufzeichnen, der eine App fährt. Zwei Vorbehalte:
- A
recordwith no workflow id is a one-shot owner, so it blocks every other workflow for its whole duration. Um gleichzeitig aufzuzeichnen und zu klicken, geben Sie beiden Befehlen denselbenWINAPP_UI_WORKFLOW_ID. - Auf einem Host ohne Frameaufnahmeunterstützung fällt die Aufzeichnung auf PrintWindow zurück, deren Wiederherstellung mit leerem Frame das Fenster jederzeit vordergrunden kann. Dort wird der Desktop für die gesamte Aufzeichnung gehalten, und der Befehl sagt dies in seiner Ausgabe; auch die Eingabe desselben Workflows wartet.
Fehler, die Möglicherweise angezeigt werden: invalid_ui_workflow_id (die Variable ist festgelegt, aber leer oder über 256 Zeichen), desktop_coordination_unavailable (Koordinationszustand ist unlesbar und kann nicht sicher neu erstellt werden oder von einem neueren winappGeschrieben werden), queue_capacity_exceeded (64 Befehle aus anderen Workflows warten bereits – die Beschränkung zählt ausländische Warteprogramme, nicht prozesse, die Sie gestartet haben, also Einträge, die zu Befehlen gehören, die beendet oder getötet wurden, belegen keinen Platz, und die Befehlswarteschlange Ihres eigenen Workflows hintereinander und nicht gegen diesen Grenzwert), ui_turn_busy (yield während Ihr eigener Workflow noch einen Befehl ausgeführt wird) und cancelled (STRG+C beim Warten, Beenden von Code 130).
Vorzeitiges Loslassen: winapp ui yield
Die Vier-Sekunden-Gnade ist ein Fallback: Sie behält den Desktop reserviert, wenn Sie nicht sagen können, dass Sie fertig sind. Wenn Sie dies sagen können , sagen Sie das – yield übergibt den Desktop sofort, anstatt allen anderen eine Gnade zu machen, die niemand braucht.
$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-Befehle sollten überhaupt keine Workflow-ID festlegen. Ohne einen loslässt jeder Befehl den Desktop bereits im Moment, in dem er abgeschlossen ist, und es gibt nichts zu ertragen.
- Mehrstufige Workflows sollten nach Abschluss der Workflows erzielt werden, insbesondere, wenn andere Workflows warten. Es kostet einen schnellen Befehl und entfernt einen Vier-Sekunden-Stall von allen anderen.
- Es ist idempotent. Zweimal oder nachdem die Gnade bereits abgelaufen ist, gelingt und berichtet
{ "released": false }– das ist das normale Ende eines Skripts, kein Fehler. - Es gibt niemals die Wendung eines anderen Workflows frei. Wenn eine andere Person den Desktop hält oder niemand tut, ist es ein no-op.
- Es schlägt fehl
ui_turn_busy, wenn Ihr eigener Workflow immer noch einen Befehl ausgeführt oder in die Warteschlange gestellt hat , z. B. eine Aufzeichnung. Die Freigabe darunter würde den Desktop mitten im Befehl übergeben, sodass nichts losgelassen wird und der ausgeführte Befehl nicht betroffen ist. Warten Sie darauf, oder beenden Sie es, und geben Sie es dann erneut zurück. - Es erfordert
WINAPP_UI_WORKFLOW_ID. Ohne einen schlägt es mitinvalid_arguments. - Es dauert keine App und keine Auswahl: Sie gibt eine Reservierung zurück, kein Fenster, sodass sie nach dem Schließen der App weiterhin funktioniert.
Ein Wartebefehl wird von wem der Desktop losgelassen wird, anstatt ihn abzufragen, sodass eine Warteschlange fast nichts kostet, während sie wartet und die Übergabe sofort erfolgt. Jeder Waiter überprüft auch gelegentlich neu, was den Desktop wiederherstellt, wenn ein Prozess getötet wird und niemals etwas veröffentlicht: Der Befehl an der Spitze der Warteschlange sieht alle halbe Sekunde aus, und Befehle dahinter – die nicht trotzdem vor dem Kopf ausgeführt werden können – alle paar Sekunden.
Ziel-Apps
Nach Prozessname
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
Einige verpackte Apps (z. B. Rechner) haben kein eigenes Fenster; ein anderer Prozess hostisiert seinen Frame. Wenn der abgeglichene Prozess (nach Name oder PID) kein sichtbares Fenster aufweist, verwendet den Frame, -a der stattdessen seinen Inhalt hostet. Wenn keines vorhanden ist (z. B. wird die App noch gestartet), -a zielt auf den Prozess ab, sodass wait-for sie so lange nachschaut, bis das Fenster angezeigt wird.
Nach Fenstertitel
winapp ui inspect -a "LICENSE - Notepad"
winapp ui inspect -a "Fix WinApp" # partial title match
Von PID
winapp ui inspect -a 12345
Von HWND (stabil – übersteht Tabstopp-/Titeländerungen)
# 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
Wird -a für die Ermittlung verwendet, -w um eine stabile Zielbestimmung zu bieten. Wenn -a sie mehreren Fenstern entsprechen, listet der Befehl sie mit HWNDs auf, die Sie auswählen können.
Selektoren
Zielelemente mithilfe der Auswahl, die in [brackets] der Untersuchungs-/Suchausgabe angezeigt wird.
Es gibt drei Arten von Selektoren:
| Selektor | Bedeutung | Example |
|---|---|---|
MinimizeButton |
AutomationId (angezeigt, wenn eindeutig – stabil, bevorzugt) | winapp ui invoke MinimizeButton -a myapp |
btn-close-d1a0 |
Semantischer Strich (wird angezeigt, wenn keine eindeutige Automatisierungs-ID vorhanden ist) | winapp ui invoke btn-close-d1a0 -a myapp |
Submit |
Nur-Text-Suche mit Name/AutomationId (Teilzeichenfolge ohne Groß-/Kleinschreibung) | winapp ui invoke Submit -a myapp |
AutomationId-Selektoren sind Entwickler-Set-IDs (AutomationProperties.AutomationId in XAML).
Wenn eine AutomationId in der gesamten UI-Struktur inspect eindeutig ist und search sie direkt als Selektor anzeigen – diese überleben Layoutänderungen, Lokalisierung und Strukturumstrukturierung.
Slug-Selektoren (z. B. ) werden generiert, btn-close-d1a0wenn keine eindeutige AutomationId vorhanden ist.
Format: prefix-name-hash. Der Hash überprüft die Elementidentität, kann aber nach Ui-Änderungen veraltet sein.
Prüfen des Ausgabeformats
Der inspect Befehl zeigt die Elementstruktur mit farbiger Ausgabe an (Selektor in Cyan, Name in Grün, Metadaten in Grau):
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
Das erste Wort in jeder Zeile ist die Selektor – verwenden Sie es mit anderen ui Befehlen.
Wenn ein Element über eine eindeutige AutomationId verfügt, wird es direkt verwendet (z. B TabView. , NewTabButton).
Wenn keine eindeutige AutomationId vorhanden ist, wird eine generierte Slug verwendet (z. B. tab-newtab-5f5b).
Semantische Striche
Slugs verwenden das Format: dabei: prefix-normalizedname-hash
- Präfix — Abkürzung vom Typ 3 Buchstaben (btn, txt, chk, cmb, itm, tab, img, lbl, pn, win, grp, lnk, mnu usw.)
- normalisierter Name – alphanumerisch in Kleinbuchstaben von AutomationId (bevorzugt) oder Name, max. 15 Zeichen
- Hash – 4-Zeichen-Hex-Hash der RuntimeId des Elements (validates element identity)
Slugs sind shellsicher (keine Sonderzeichen), eindeutig und können direkt als Argumente verwendet werden. Ohne Abfragefilter bietet der Hash veraltete Erkennung – wenn das Element ersetzt wurde, erhalten Sie Folgendes: "Element hat sich möglicherweise geändert. Prüfung erneut ausführen." Informationen zu gefilterten Abfragen finden Sie unter "Bereichsbezogene und eingegebene Abfragen".
Elemente ohne Namen oder AutomationId zeigen nur Präfix + Hash an (z. B. pn-c8a3).
Mehrdeutige Übereinstimmungen
Slugs from inspect/search output are unique, but can change across layout changes - use them over plain type names or text when multiple matches. Wenn eine Auswahl mehrdeutig ist, druckt die CLI alle Übereinstimmungen mit ihren Slugs, sodass Sie das richtige auswählen und mit diesem Slug erneut ausführen können.
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
Nur-Text-Suche
Verwenden Sie Nur-Text, um nach Elementen zu suchen – keine spezielle Syntax erforderlich:
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
Wenn eine Textsuche mehreren Elementen entspricht (z. B. SettingsExpander, wobei "Group", "Button" und "Text" denselben Namen aufweisen), wählt die CLI automatisch das einzige aufrufende Element aus. Wenn mehrere aufrufen können, werden alle Übereinstimmungen mit Slugs aufgelistet.
Bei nicht aufrufenden Suchergebnissen (z. B. einem TextBlock innerhalb einer Schaltfläche) zeigt die Suche automatisch den nächsten aufrufenden Vorgänger an – das übergeordnete Element, mit invokedem Sie arbeiten können.
Dies funktioniert für alle Suchmarkierer:
lbl-savechanges-a1b2 "Save changes" (120,40 80x20)
^ invoke via: btn-save-c3d4 "Save"
Die oberflächenierte Selektor kann direkt verwendet werden:
winapp ui invoke btn-save-c3d4 -a myapp # invoke the parent Button
Commands
status
Stellen Sie eine Verbindung mit einer App her, und zeigen Sie Verbindungsinformationen an.
winapp ui status -a notepad
winapp ui status -a notepad --json
Überprüfen
Zeigen Sie die Ui-Elementstruktur an. Die Ausgabe zeigt semantische Schrägstriche mit zwei Leerzeichen für die Hierarchie an:
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
Beispielausgabe (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)
Beispielausgabe (--interactive — nur Aktionen erfordernde Elemente, flache Liste):
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)
Elemente können diese Zustandsmarkierungen anzeigen:
-
[on]/[off]/[indeterminate]— Umschalten/Kontrollkästchenstatus -
[collapsed]/[expanded]— Erweitern/Reduzieren des Zustands für Bäume, Kombinationsfelder, Menüelemente -
[scroll:v]/[scroll:h]/[scroll:vh]— Bildlaufcontainer (vertikal, horizontal oder beides) -
[offscreen]— Element ist auf dem Bildschirm nicht sichtbar -
[disabled]— Element ist nicht aktiviert -
value="..."— aktueller Textinhalt für bearbeitbare Elemente (bei unterschiedlichem Namen)
search
Suchen Sie Elemente, die mit einer Auswahl übereinstimmen. Ausgabe zeigt semantische Slugs:
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
Beispielausgabe:
btn-minimize-d1a0 "Minimize" (1222,206 48x48)
btn-maximize-e2b1 "Maximize" (1270,206 48x48)
btn-close-d1a2 "Close" (1318,206 48x48)
Slugs, die in der Ausgabe (z. B. ) angezeigt werden, btn-minimize-d1a0können direkt mit anderen Befehlen verwendet werden:
winapp ui invoke btn-minimize-d1a0 -a notepad
get-property
Dient zum Lesen von Eigenschaftswerten aus einem Element. Enthält musterspezifischen Zustand (ToggleState, Value, IsSelected usw.).
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
Bei Eigenschaftsnamen muss die Groß-/Kleinschreibung beachtet werden. Ein unbekannter Name schlägt mit invalid_arguments "unter --json" fehl. Lassen --property Sie die Eigenschaften weg, einschließlich aller sechs unten aufgeführten Textformatierungsattribute.
wait-for --property verwendet die gleichen Namen mit Beachtung der Groß-/Kleinschreibung und lehnt unbekannte Namen vor der Abfrage ab.
Formatierung von Text im gesamten Dokument
Die Formatierung wird über das gesamte TextPattern-Dokument des Elements gelesen, nicht über die aktuelle Auswahl oder caret. Lesevorgänge ändern den Fokus oder die Auswahl nicht.
| Eigenschaft | Uniform-Wert (zurückgegeben als Zeichenfolge) |
|---|---|
FontWeight |
Numerische Gewichtung, z "400" . B. (Normal) oder "700" (fett) |
FontName |
Schriftartfamilienname, z. B. "Courier New" |
FontSize |
Größe in Punkt, z. B. "15.5" |
ForegroundColor |
Dezimal Windows COLORREF (0x00BBGGRR), "3678732" z. B. für RGB(12, 34, 56) |
IsItalic |
"True" oder "False" |
StrikethroughStyle |
Numerische UIA-Text-Dekorationsart, z "0" . B. (keine) oder "1" (single) |
Zahlen verwenden eine invariante Formatierung (ein Dezimalkomma, unabhängig vom Gebietsschema). Jedes Attribut kann stattdessen folgendes zurückgeben:
| Wert | Bedeutung und nächster Schritt |
|---|---|
"Mixed" |
Die Formatierung variiert innerhalb des Dokuments. Behandeln Sie sie nicht als einheitlicher Wert; Dieser Befehl fragt keine einzelnen Textbereiche ab. |
"NotSupported" |
Der TextPattern-Anbieter des Dokuments meldet dieses Attribut nicht. Überprüfen Sie die Barrierefreiheitsunterstützung der App. |
"Unavailable" |
Das Element hat keinen TextPattern. Verwenden oder search suchen Sie inspect das zugehörige Text-/Dokumentelement. |
Beim Auflisten aller Eigenschaften bleiben zwischengespeicherte grundlegende Eigenschaften verfügbar, wenn kein Liveelement aufgelöst werden kann, und ein falsch formatierter Formatierungswert wird weggelassen, ohne andere Eigenschaften zu verwerfen. Diese Auslassungen werden als Warnungen protokolliert. Fordern Sie eine bestimmte Formatierungseigenschaft an, um einen Fehler anstelle einer Auslassung zu erhalten.
Anbieterfehler bleiben Fehler, nicht "Unavailable". Überprüfen stale_elementSie die App erneut, und wiederholen Sie den Vorgang mit einer aktuellen Auswahl.
Der JSON-Umschlag enthält elementId, einen typierten elementund Zeichenfolgenwert properties.
Vorhandene Eigenschaften, einschließlich BoundingRectangle, behalten ihre Formate bei.
Beispielsweise lautet der Formatierungsteil von properties :
{
"FontWeight": "700"
}
Screenshot
Erfassen Sie ein Fenster oder Element als 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)
Ohne elementauswahl kombiniert die Standardaufnahme mehrere Fenster in einem beschrifteten, nebeneinander zusammengesetzten PNG-Format, nicht in separaten Dateien.
-a nach Prozessname oder PID umfasst die Fenster der App und ihre eigenen Fenster. Eine titelbasierte -a Übereinstimmung wählt ein übereinstimmende Fenster sowie seine eigenen Fenster aus; -w wählt explizit ein Fenster plus seine eigenen Fenster aus, nicht jedes Fenster im Prozess. Ein eigenes Dialogfeld oder eine Eigene QuickInfo kann daher auch dann als eigenes Panel angezeigt werden, wenn Sie den Haupt-HWND explizit auswählen. Ein Elementmarkierer bezieht sich auf dieses Element, anstatt Fenster zu erstellen. Ein Element in einem Menü, Flyout, QuickInfo oder Lehrtipp, das in einem eigenen Popupfenster geöffnet wird, wird aus diesem Popup und nicht aus dem Fenster dahinter zugeschnitten.
--quiet Unterdrückt die Informationsausgabe sowohl für Einzelfenster- als auch für zusammengesetzte Erfassungen, einschließlich des gespeicherten Pfads. Warnungen und Erfassungsfehlerdiagnose bleiben sichtbar. Verwenden Sie --json stattdessen, wenn Sie den Dateipfad und die Dimensionen als strukturierte Ausgabe benötigen.
Benannt mit --on sandboxdem --output Namen des Hostziels. Erfolgreiche einfache Ausgabe und --json Bericht über den Hostpfad nach dem Senden des Bilds.
Der Standardaufnahmepfad verwendet Windows. Graphics.Capture (WGC) liest die tatsächliche DWM-zusammengesetzte Oberfläche – wobei abgerundete Ecken, Transparenz und Arbeit beibehalten werden, auch wenn das Fenster von anderen windows verdeckt wird. Wenn WGC nicht verfügbar ist (ältere Windows Builds), greift die CLI auf PrintWindow zurück.
Verwenden Sie diese Funktion --capture-screen -w <hwnd> , wenn Sie sichtbare Popups oder QuickInfos an ihren Bildschirmpositionen benötigen, einschließlich Überlagerungen, die nicht dem Zielfenster gehören. Er liest den Bildschirmbereich des Fensters vor, anstatt beschriftete Bereiche zu erstellen und das Fenster zuerst in den Vordergrund zu bringen. Bei -adiesem Vorgang ist genau ein übereinstimmende Fenster erforderlich. Wenn mehrere Fenster der obersten Ebene oder im Besitz übereinstimmen, verwenden winapp ui list-windows -a <app> Und wiederholen Sie den Vorgang.-w <hwnd> Verwenden Sie diese Funktion --focus , wenn Sie das Fenster nur im Vordergrund stellen möchten, ohne die Aufnahmemodi zu wechseln (z. B. um sicherzustellen, dass der Screenshot dem aktuellen Benutzer entspricht).
Da der Bildschirm DC alles erfasst, was sich tatsächlich im Vordergrund befindet, überprüft,
--capture-screenob das Ziel unmittelbar vor dem Erfassen erreicht wurde, und schlägt fehlforeground_not_target, wenn dies nicht der Fehler ist (Fokus-Stealing Prevention, eine UAC-Eingabeaufforderung oder ein anderes Fenster, das sich selbst aktiviert). In diesem Fall ist kein Bild geschrieben – zuvor beendete der Befehl 0 und gab ein Bild des falschen Fensters zurück.ui record --capture-screenwendet die gleiche Prüfung vor dem ersten Frame an.
Datensatz (record)
Zeichnen Sie ein Fenster oder einen Elementbereich in einem H.264 MP4 auf. Bevorzugen Sie ein Positives --duration-sec für unbeaufsichtigte Skripts. Ohne Dauer wird die Aufzeichnung bis STRG+C oder für umgeleitete Stdin, eine Neueinleitung oder EOF fortgesetzt. Für npm uiRecord und targetRecord Hilfsprogramme ist eine ganze Zahl durationSec von 1 bis 86400 erforderlich. Das abbruchsignal bricht kraftvoll ab, anstatt eine Aufzeichnung ordnungsgemäß abzuschließen.
# 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
Optionen:
-
--duration-sec N— Datensatz für N Sekunden. Standard 0 Datensätze, bis sie beendet wurden. -
--fps N— Zielframes pro Sekunde (Standard 15). -
--max-edge N— Abwärtsskalen, sodass die längste Kante höchstens N Pixel beträgt (0 = keine Abwärtsskalen). -
--capture-screen— Aufnahme vom Bildschirm DC (einschließlich Überlagerungen/Popups; Vordergrund des Fensters). -
--output <path>— Ausgabe MP4-Pfad. Wird standardmäßig aufrecording-<timestamp>-<guid>.mp4festgelegt. -
--overwrite— Ersetzen Sie vorhandene Aufzeichnungsausgaben, nachdem die neue Aufnahme abgeschlossen wurde. Ohne dies werden vorhandene Ausgaben abgelehnt. -
--frames— Schreiben Sie zeitstempelte JPEG-Nachweise in<output-name>.frames. Unterstützt 1-30 fps und--max-edge64-4096 (Standard 1280). Framedaten sind auf 1 GiB begrenzt; der MP4-Vorgang fortgesetzt wird, wenn die Obergrenze erreicht ist.
Agentlesbare Frameartefakte:
evidence.mp4
evidence.frames/
manifest.json
frames.ndjson
frames/
frame-000000-t000000000012.jpg
frames.ndjsonhat eine Zeile pro Probe mit sampleIndex, monotonen elapsedMs, MP4-relativen mediaTimeMs, , imageIndexund filechanged. Aufeinander folgende Pixel-identische Proben verwenden die vorherige Qualität-85 JPEG.
manifest.json zeichnet die Anforderung, die Anzeigedauer, den MP4-Status, die Bildabmessungen und den Status auf (complete, partialoder truncated). Abgeschnittene Anzeigedauer deckt das beibehaltene Präfix ab, während video das vollständige MP4 beschrieben wird.
Wählen Sie einen neuen Ausgabepfad aus, es sei denn, Sie möchten eine Aufzeichnung durch --overwriteersetzen.
Ohne das Video wird die Aufzeichnung entweder durch ein vorhandenes Video oder sein gekoppeltes .frames Verzeichnis blockiert, auch wenn Sie die Aufzeichnung auslassen --frames.
Die vorherige MP4 bleibt intakt, wenn die neue Aufnahme fehlschlägt. Bei erfolgreicher Ersetzung wird das vorherige Frameverzeichnis beibehalten, <output-name>.frames.previous-<id>auch wenn die neue Aufzeichnung ausgelassen wird --frames. Bewahren Sie teilweise Nachweise auf, und folgen Sie dem gemeldeten recoveryHint , bevor Sie den Vorgang wiederholen. Wenn die MP4-Finalisierung fehlschlägt, können beibehaltene Frames unter <output-name>.frames.partial-*veröffentlicht werden. Frameartefakte enthalten unverschlüsselte Bildschirminhalte; behandeln Sie sie wie Screenshots oder Videos.
Mit --on sandbox, sowohl das MP4- als auch das Frameverzeichnis werden an den Host übermittelt, einschließlich Der Standardausgabe, wenn --output nicht angegeben wird. Siehe Sandkastenerfassung für unterbrochene Aufzeichnungen und aufzeichnungen des gesamten Desktops.
Aufnahmemodi (im JSON-Feld mode angegeben):
-
wgc— Windows Grafikaufnahme (Standard; funktioniert, während das Fenster verdeckt ist). -
printwindow— GDI PrintWindow (Fallback, wenn WGC auf diesem System/dieser Sitzung nicht verfügbar ist; führen Sie stattdessen eine Erneute Ausführung mit--capture-screenBildschirm DC aus). -
screen— Bildschirm DC via--capture-screen(enthält Überlagerungen/Popups; bringt das Fenster in den Vordergrund).
JSON-Ausgabe (--json):
-
stdout: Endgültiges Aufzeichnungsergebnis, einschließlich Kadenz, Stoppgrund, optional
frameArtifactsund Warnungen. -
stderr: Ein JSON-Objekt pro Zeile: ein
recording-startedEreignis nach dem ersten Frame, gefolgt von einem Fehler, wenn die Aufzeichnung später fehlschlägt. Framepfade sind nur enthalten, wenn die Frameausgabe aktiv ist.
Fehlercodes:
-
element_not_found— Die Auswahl wurde nicht übereinstimmen. -
ambiguous_selector— Der Selektor hat mehrere Elemente abgeglichen; verwenden Sie einen vorgeschlagenen Strich. -
invalid_arguments– Ein Optionswert ist ungültig. -
output_exists— Eine Aufzeichnungsausgabe ist bereits vorhanden und kann nicht unter den angeforderten Optionen ersetzt werden. -
frame_output_failed– Es konnte kein Artefakt beibehalten werden, nachdem die Frameausgabe fehlgeschlagen ist. -
partial_output— Nur ein Artefakt wurde abgeschlossen; prüfenpartialOutputundrecoveryHint.
Ein Elementmarkierer zeichnet den Bereich dieses Elements aus dem Fenster auf, in dem es gezeichnet wird. Für ein Element in einem Menü, Flyout, QuickInfo oder Lehrtipp, der in einem eigenen Popupfenster geöffnet wird, zeigt die Aufzeichnung das Popup anstelle des Fensters dahinter an.
Aufrufen
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
Wird verwendet --action , wenn ein Test einen bestimmten Vorgang für genau das ausgewählte Element ausführen muss. Es versucht niemals ein anderes Muster oder einen aufrufenden Vorgänger, auch wenn die angeforderte Aktion fehlschlägt. Ein Steuerelement, das sowohl Aufrufe als auch Auswahl unterstützt, wird ausgewählt, nicht aufgerufen, mit --action select. Bei --actioneinem Slug wird genau auf ein Element ausgerichtet. Ein Nur-Text- oder AutomationId-Selektor, der mehreren Elementen entspricht, schlägt mit einem nichtzero-Ausgangscode geschlossen, anstatt auf die erste Übereinstimmung zu handeln. Übergeben Sie daher einen Schrägstrich, wenn inspect/search ein Name mehrdeutig ist.
--root, --typeund --class-name schränken Sie die Übereinstimmung ein, wie in bereichsbezogenen und eingegebenen Abfragen beschrieben, mit oder ohne --action.
Wird verwendet -w <dialog-HWND> , um eine Aktion auf dieses Dialogfeld zu beschränken oder -a <app> die Fenster der App einzuschließen. Ein gefilterter Aufruf bestätigt das eindeutige Ziel vor dem Handeln, erfordert genau ein übereinstimmendes Element und wechselt nie zu einem anderen Fenster oder einem aufrufbaren Vorgänger. Null-Übereinstimmungen schlagen mit element_not_foundfehl; Duplikate schlagen mit ambiguous_selector. Ein veraltetes Element oder ein wiederverwendetes Fenster schlägt fehl, ohne zu handeln; Führen Sie die Ausführung inspect erneut aus, oder search wählen Sie einen aktuellen Selektor aus.
Ohne --action, versucht ein gefilterter Aufruf weiterhin die Muster in der Reihenfolge für dieses ein Element.
| Action | Operation |
|---|---|
invoke |
InvokePattern.Invoke |
select |
SelectionItemPattern.Select |
toggle |
TogglePattern.Toggle, genau einmal |
toggle-on / toggle-off |
Read ToggleState; erfolgreich, ohne einen bereits korrekten Zustand zu ändern, andernfalls umschalten und überprüfen |
expand / collapse |
ExpandCollapsePattern.Expand / Collapse |
Für toggle-on und toggle-off, ein Startzustand Indeterminate ermöglicht höchstens zwei Übergänge, wobei der Zustand nach jedem überprüft wird. Andere Startzustände ermöglichen einen Übergang. Wenn der angeforderte Zustand nicht erreicht ist, schlägt der Befehl fehl, anstatt den Umschalter fortzusetzen. Bei einer fehlgeschlagenen Überprüfung kann das Steuerelement geändert werden; lesen, ToggleState bevor Sie entscheiden, was als Nächstes zu tun ist.
Ohne --action und ohne Filter ist das automatische Verhalten unverändert: Try InvokePattern, TogglePattern, SelectionItemPattern, then ExpandCollapsePattern (expand), with anvokable-ancestor retry when needed.
Eine nicht unterstützte Aktion schlägt mit einem nichtzero-Beendigungscode und, mit --jsoneinem strukturierten Fehler auf stderr, fehl. Überprüfen Sie das ausgewählte Steuerelement, und wählen Sie eine von ihr unterstützte Aktion aus, oder richten Sie das beabsichtigte übergeordnete Element explizit aus. Success JSON includes requestedAction and performedAction; see the JSON reference.
klicken
Klicken Sie mit der Maussimulation auf ein Element an seinen Bildschirmkoordinaten. Verwenden Sie diese Option für Steuerelemente, die nicht unterstützt InvokePattern werden (z. B. Spaltenüberschriften, Listenelemente).
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
Wie bei den anderen Eingabeinjizierverben
clickwird das Ziel im Vordergrund angezeigt und schlägt schnell (no_interactive_desktopauf einem gesperrten/sicheren Desktop,foreground_not_targetwenn der Fokus nicht übertragen werden konnte) statt auf das falsche Fenster zu klicken. Außerdem wird das Element direkt vor der Schaltfläche nach unten aufgelöst: Nach der Positionierung des Cursors schlägt eine endgültige Positionsüberprüfung fehl, sodass ein fortlaufendes Bewegen/Animieren des Ziels fehlschlägttarget_moved, anstatt erfolglos zu melden, nachdem der Klick auf einen leeren Bereich geklickt wurde – ein gemeldeter Erfolg bedeutet, dass das Ziel noch vorhanden war, wenn die Schaltfläche nach unten ging.
Drag
Drücken Sie die Maustaste an einem Punkt, wechseln Sie zu einem anderen, und lassen Sie los drag <from> <to>, wobei jeder Endpunkt entweder ein Elementmarkierer ist (zieht von/in die Mitte des Elements) oder Bildschirmkoordinaten x,y genau wie gemeldet von winapp ui inspect. Mischen sie frei (Selektor→Auswahl, Selektor→Koordnen, Koordnen→Koordnen).
Wird mit zwischengeschalteten Verschiebungen verwendet SendInput , damit die App einen realistischen Nachrichtenstrom WM_MOUSEMOVE sieht. Verwenden Sie sie zum Neuanordnen/Ändern der Größe von Ziehpunkten, Schiebereglern, Zeichenbereichszeichnungen und Ziehen und Ablegen.
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
Optionen:
-
--right– Ziehen Sie mit der rechten Maustaste anstelle der linken Schaltfläche. -
--hold-ms <ms>— Halten Sie die Schaltfläche am Anfang gedrückt, bevor Sie navigieren (Standard: 0). Bei<from> == <to>(ohne Bewegung) führt dies eine Gedrückt-/Lange Gedrückthalten-Geste durch. -
--dwell-ms <ms>— Dwell am Ziel nach dem Verschieben vor dem Loslassen (Standard: 0). Ermöglicht das Ablegen von Zielen/Zusammenführen von Überlagerungen , die von einem dauerhaften Daraufzeigen (statt dem Moment, an dem der Cursor eingeht), vor der Schaltfläche nach oben zu ziehen.
Bare
x,ysind Bildschirmkoordinaten im gleichen Raumberichtwinapp ui inspect/search, und eine Auswahl wird in die Mitte des Elements aufgelöst – prüfen Sie zuerst, um Punkte auszuwählen.
Wie
send-keys --via send-input,dragfügt betriebssystemweite Bildschirmkoordinaten ein, nachdem das Ziel in den Vordergrund gebracht wurde. Wenn der Fokus nicht zum Ziel gebracht werden kann (z. B. Die Verhinderung des Fokusdiebstahls aus einem Hintergrundprozess), schlägt der Befehl fehl (foreground_not_target) statt auf das falsche Fenster zu ziehen – fokus oder klicken Sie zuerst auf das Fenster. Auf einem gesperrten/sicheren Desktop schlägt er mitno_interactive_desktop. Jeder Elementendpunkt wird unmittelbar vor dem Ziehen erneut aufgelöst. wenn die Größe noch verschoben/geändert wird (ein Animationsziel), schlägt der Befehl fehltarget_moved, anstatt auf einen veralteten Punkt zu ziehen. (Barex,yEndpunkte können nicht erneut überprüft werden, sodass sie as-isverwendet werden.)
Berühren
Fügen Sie synthetische Touchgesten mithilfe der Windows Zeigereinfügungs-API ein. Der Kontaktanker ist entweder eine Elementauswahl (verwendet die Mitte des Elements) oder eine explizite Bildschirmkoordinate x,y über --at (dieselben Leerzeichenberichte winapp ui inspect ). Verwenden Sie sie für Tippen-/Drücken-Interaktionen und Multitouchgesten, die die Maussimulation nicht ausdrücken kann.
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)
Optionen:
-
--gesture <g>—tap(Standard),double-tap, ,long-pressswipe,pinch, .stretch -
--at <x,y>— Expliziter Startpunkt (Bildschirmkoordinaten). Standardmäßig wird das Elementcenter des Selektors zentriert. -
--to-point <x,y>— Endpunkt für einswipe. Hat Vorrang vor--direction. -
--direction <right|left|up|down>— Streifrichtung (Standard:right). Kombiniert mit--distanceder Berechnung des Endpunkts, wenn--to-pointer nicht angegeben wird. -
--distance <px>– Fingerbreite fürpinch/stretchoder Wischenabstand in Pixeln. -
--hold-ms <ms>— Halten Sie Kontakte gedrückt, bevor Sie das Heben aufheben (lange gedrückt halten; ist standardmäßig 500 ms lang, wennlong-presssie nicht festgelegt ist). -
--duration-ms <ms>— Gleitzeit für Bewegungsgesten (Wisch-/Zusammendrücken/Strecken; Standard 300). -
--fingers <n>— Anzahl der Kontakte (1 bis 10; Standard 1).pinch/stretchimmer 2 verwenden.
Injektionssicherheit.
touchverweigert das Einfügen, es sei denn, ein Nicht-Null-Zielfensterziehpunkt wird aufgelöst, und das Fenster enthält den Vordergrund . Es schlägt fehlno_target, wenn kein Fenster aufgelöst werden kann,foreground_not_targetwenn der Fokus nicht übertragen werden konnte, oderno_interactive_desktopauf einem gesperrten/sicheren Desktop. Jede Koordinate (Elementzentrierung, explizite--at/--to-pointund generierte Wegpunkte) wird gegen das Zielfensterrechteck überprüft. Ein Punkt außerhalb des Fensters wird als nicht tödliche Warnung (ein Eintrag inwarnings[]oder eine Warnzeile im Textmodus) angezeigt, und das Einfügevorgang wird weiterhin fortgesetzt – mit den Mausverben (--jsonclick/drag/hover/), die auch beiscrolleingefügt werden.--fingersüber 10 wird im Vorfeld abgelehnt.Hardwarehinweis. Touch bevorzugt das moderne synthetische Zeigergerät (
CreateSyntheticPointerDevice(PT_TOUCH)) und greift auf die Legacy-APIInitializeTouchInjection/InjectTouchInputzurück. Wenn die Einfügung auf dem aktuellen Gerät/der aktuellen Sitzung nicht unterstützt wird, zeigt der Befehl den tatsächlichen Win32-Fehlercode (z. B. "nicht unterstützt") an, anstatt einen falschen Erfolg zu melden – behandeln Sie einen Nicht-Null-Exit als "Touch nicht zugestellt".Remotedesktop/VM-Sitzungen. In einem Remotedesktop (RDP) oder einigen VM-Sitzungen akzeptiert das Betriebssystem möglicherweise synthetische Toucheingabe (Exit 0), ohne die Ziel-App tatsächlich zu erreichen. Wenn eine Remotesitzung erkannt wird,
touchwird eine Warnung zur Übermittlungsunsicherheit angefügt – einwarnings[]Eintrag in--jsonoder eine Warnzeile im Textmodus. A ✅/exit 0 bedeutet dann, dass der Einfüfungsaufruf erfolgreich war, nicht dass die App die Eingabe erhalten hat; bestätigen Sie den Effekt,ui screenshot/ui inspectwenn es wichtig ist.
Stift
Einfügen synthetischer Zeichen-/Eingabestifte – Tippen und Freihandstriche – mit der Windows synthetische Zeiger-API (CreateSyntheticPointerDevice(PT_PEN); Windows 10 1809+). Ziel eines Elementcenters, eines expliziten --at Punkts oder eines vollständigen --path Freihandstrichs.
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
Optionen:
-
--at <x,y>— Stiftkontaktpunkt (Bildschirmkoordinaten). Standardmäßig wird das Elementcenter des Selektors zentriert. Wird ignoriert, wenn--pathangegeben wird. -
--path "<x,y x,y …>"— Freihandstrichpfad als leerzeichentrenntex,yPaare (ein Punktpfad ist ein Tipp). -
--pressure <0.0–1.0>— Stiftdruck (Standard 0,5). -
--tilt-x <deg>/--tilt-y <deg>— Stiftneigungswinkel, −90 bis 90 (Standard 0). -
--eraser— Verwenden Sie das Radiererende des Stifts anstelle der Spitze. -
--duration-ms <ms>— Gesamtdauer der Strichlaufzeit in Millisekunden, die als interpolierte UPDATE-Frames über den Pfad verteilt werden (Standard: ~10 ms pro Waypoint). Verwenden Sie dies, um zu steuern, wie schnell der Stift von Anfang zu Ende bewegt wird.
Injektionssicherheit. Wie
touchwirdpendie Einfügefunktion ohne ein Nicht-Null-, Vordergrund-Zielfenster (no_target/foreground_not_target/no_interactive_desktop) verweigert und jeder Freihandpunkt gegen das Zielfensterrechteck überprüft, wobei eine out-of-window-Koordinate als nicht tödliche Warnung (warnings[]in--jsonoder eine Warnzeile im Textmodus) angezeigt wird, während sie immer noch injiziert wird – konsistent mit den Mausverben. Ungültig--pressure(außerhalb von 0,0–1,0) oder Neigung (außerhalb ±90°) wird vorn abgelehnt.Remotedesktop/VM-Sitzungen. Das Stiftrouting ist besonders unzuverlässig über Remotedesktop: Der Einfügeaufruf kann Erfolg melden (Exit 0), während keine Stifteingabe die App erreicht. Wenn eine Remotesitzung erkannt wird,
penwird eine Warnung zur Übermittlungsunsicherheit (warnings[]in--json, oder eine Warnzeile im Textmodus) angefügt, sodass eine ✅ nicht für die bestätigte Zustellung verwechselt wird. Überprüfen Sie stiftabhängige Flüsse auf einem lokalen, interaktiven Desktop.
schweben
Bewegen Sie die Maus in die Mitte eines Elements, um Hovereffekte (QuickInfos, Flyouts, visuelle Zustände) auszulösen. Wird SendInput für eine realistische Mausbewegung mit einem kleinen Wiggle verwendet und wartet dann auf eine konfigurierbare Verweilzeit.
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
Optionen:
-
--dwell-time <ms>— Zeit in Millisekunden, bis nach dem Daraufzeigen auf Effekte gewartet wird (Standard: 800, Bereich: 0–10000)
Send-Keys
Senden Sie synthetische Tastatureingaben – das Gegenstück zur Tastatur an click. UIA hat kein Tastatureinfügungsmuster, sodass dies auf die Win32-Ebene fällt. Verwenden Sie sie für die Tastaturnavigation (Pfeile, TAB, EINGABETASTE, ESC), Tastenkombinationen (ctrl+c, ), und geben Sie Steuerelemente ein, alt+f4die Tastatureingabeereignisse erfordern, anstatt set-valueatomisch zu schreiben.
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
Schlüsselgrammatik (leerzeichentrennte Token, Anführungszeichen mit mehreren Tokenzeichenfolgen):
-
Benannte Schlüssel -
enter/return, ,tab,esc/escape,spacebackspacedelete/del,inserthomeendpageup/pguppagedown/pgdnup/down/left/right-f1f16,apps, , . .printscreencapslock -
Sequenzen - mehrere Token werden in der Reihenfolge gedrückt:
down down enter. -
Modifizierer-Kombinationen —
ctrl,shift, ,altverbundenwinmit+:ctrl+shift+t,alt+f4. Ein Token, das mit einem Modifizierer beginnt, aber ein unbekanntes Segment vor dem letzten (ctrl+a+b) hat, ist ein Fehler; verwendentext=oder--verbatimeingeben. -
Befehle der Sprachausgabe – Halten
capslockoderinsert(Aliasins), die Sprachausgabe, NVDA und JAWS-Taste:ctrl+capslock+f12Schaltet den Entwicklermodus der Sprachausgabe ein. Erfordert--via send-input, da Bildschirmsprachausgaben keine geposteten Schlüssel erhalten. Wenn keine Sprachausgabe ausgeführt wird,capslockwird die FESTSTELLTASTE ein- oder ausgeschaltet, und der Befehl warnt. Halten Sie diesinsertzu vermeiden. -
Literaltext – jedes Token, das kein bekannter Schlüssel ist, wird nach Zeichen eingegeben:
hello. Benachbarte Literalwörter behalten den Abstand zwischen ihnen bei, sodass ein an zitierter Ausdruck wie"Hello world""Verbatim" eingegeben wird (das Leerzeichen bleibt erhalten). Ein Literal, das lediglich+text enthältC++odera+bals Text eingegeben wird und nicht als Kombination analysiert wird. -
Explizites Literal escape - Präfix eines Tokens mit dem Präfix, mit
text=dem es eingegeben werden soll, auch wenn es mit einem Schlüssel- oder Modifizierernamen kollidiert:text=enterGibt das Wort "enter" ein, anstatt die EINGABETASTE zu drücken, undtext=ctrl+agibt die Literalzeichenfolge ein. Spiegelt dasvk=Escapezeichen; der escaped-Wert wird immer noch mit benachbarten Literalwörtern (text=down low→ "unten niedrig") zusammengefasst. Da Token Leerzeichen teilen (und benachbarte Literale mit einem einzigen Leerzeichen neu verknüpft werden), verwenden Sie umgekehrte Schrägstriche innerhalb einestext=Werts , um Leerzeichen einzugeben, die andernfalls nicht überleben würden:\s→ Leerzeichen,\t→ Tabstopp,\n→ Neueline,\r→ Neueinbruch,\\→ Literalrückslass.\n,\rund\r\nfügen Sie jeweils einen einzelnen Zeilenumbruch (ein Eingabetaste /VK_RETURN) ein, undtext=line1\nline2text=line1\r\nline2geben Sie beide eine Neue zeile ein. Gibt alsotext=a\s\sb"a b" (Doppeltes Leerzeichen) ein undtext=\shibehält einen führenden Raum bei. Eine unerkannte Flucht (z. B.\x) bleibt unerkannt. -
Literal () mit ganzem Argument –
--verbatimwenn die gesamte Nutzlast Literaltext ist, übergeben--verbatimSie anstelle jedes Tokens mittext=. Es gibt das gesamte Schlüsselargument genau so ein, wie angegeben – kein benannter Schlüssel/Kombinations-/vk=/text=Interpretationstyp – und behält im Gegensatz zum normalen Pfad genaue interne Leerzeichen (keine Kollapsierung) bei, ohne dass eine Verbindung erforderlich\sist. Geben Sie alsosend-keys "down down enter" --verbatimdie Wörter ein, undsend-keys "a b" --verbatimbehalten Sie den doppelten Abstand bei. Umgekehrte Schrägstriche werden nicht im--verbatimModus decodiert (ein\sumgekehrter Schrägstrich und ein "s"); verwenden Sie eintext=Token, wenn Sie ein Escapezeichen für ein Steuerelement benötigen. -
Unformatierte virtuelle Schlüssel –
vk=0xNN(Hexadezimal) odervk=NN(dezimal) für Schlüssel ohne Anzeigenamen.
Optionen:
-
--target <selector>— Fokus dieses Elements (über UIA) vor dem Senden von Schlüsseln. Ohne das Element wechseln Schlüssel zum aktuell fokussierten Element der App. -
--verbatim— Geben Sie das gesamte Schlüsselargument als Literaltext ein (kein Schlüssel/Kombinations-/vk=/text=Analysezeichen), und bewahren Sie genaue Leerzeichen auf. Die Form des gesamten Arguments des Escapezeichens pro Tokentext=. -
--via <transport>—post-message(Standard) BeiträgeWM_KEYDOWN/WM_KEYUP/WM_CHARin der Warteschlange des Zielfensters. Es ist HWND-gezielt und umgeht UIPI (funktioniert über Integritätsstufen hinweg).send-inputfügt osweit einSendInputund wechselt zum Vordergrundfenster.
Auswählen eines Transports/ bekannter Grenzwerte:
-
post-messageist die Standardeinstellung, da uiPI umgangen wird und nicht vom Vordergrundfenster abhängt. Grenzwerte: Es kann keine globalen Hotkeys auslösen, die überWH_KEYBOARD_LLLow-Level-Hooks registriert wurden (diejenigen tippen vor der Eingabe vor einer Fensterwarteschlange), und Apps, die den Unformatierten Schlüsselstatus lesenGetAsyncKeyState, dürfen keine gehaltenen Modifizierer beobachten. Es löst automatisch das untergeordnete Fenster des Zielthreads (überGetGUIThreadInfo) nach dem Vordergrund auf, sodass klassische Win32/WinForms-Apps, deren Steuerelemente separate untergeordnete Fenster sind, Tasten erhalten, ohne manuell auf das Steuerelement abzielen zu müssen. WinUI 3 / UWP-Apps verfügen über fensterlose XAML-Steuerelemente ohne untergeordnete hWND, sodass ein gepostetesWM_CHAR/WM_KEYDOWNElement nichts zum Landen hat und gelöscht wird . Postnachrichten können sie nicht steuern (der Befehl warnt und beendet 0); Verwenden Sie .--via send-input(WPF Fenster sind single-HWND und Routingschlüssel an das intern fokussierte Element, sodass die Postnachricht dort funktioniert.) -
send-inputerzeugt vollständig reale Eingaben (Modifizierer, die sichtbar sindGetAsyncKeyState, löst Hooks auf niedriger Ebene aus), wechselt jedoch in das Vordergrundfenster und wird durch UIPI blockiert, wenn ein Prozess mit erhöhten Rechten in ein Ziel mit niedrigerer Integrität (AppContainer/AppX) eingefügt wird. Wennsend-inputein Fehler gemeldet wird, wird das Ziel wahrscheinlich erhöht oder eine AppX-App verwendet,post-messageoder führen Sie die CLI auf einer übereinstimmenden Integritätsebene aus. Als Sicherheitsschutz wird überprüft,send-inputob sich das Zielfenster unmittelbar vor dem Einfügen im Vordergrund befindet, und schlägt (foreground_not_target) fehl, anstatt in das falsche Fenster einzugeben , wenn der Fokus nicht darauf gesetzt werden konnte – Fokus oder klicken Sie zuerst auf das Fenster. Auf einem gesperrten oder sicheren Desktop schlägt sie stattdessen fehlno_interactive_desktop(es ist kein Vordergrundfenster vorhanden, in das die Sitzung eingefügt werden soll) – entsperren Sie die Sitzung, oder verwenden Sie ein UIA-Musterverb (set-value,invoke). -
Systemgeschützte Kombinationen (
win+l, ,win+r,ctrl+shift+esc,ctrl+alt+del,alt+tabalt+f4, , ,ctrl+esclonewin/printscreen, ...) wirken auf das Betriebssystem/die Shell und nicht nur auf das Ziel, wenn das Betriebssystem breit gesendet wird.send-inputlehnt sie standardmäßig ab (Fehler mitinvalid_argumentsund sendet nichts), da das Einfügen auf Betriebssystemebene Auswirkungen hat, die weit über das Zielfenster hinausgehen (z. B.win+lwürde die Sitzung sperren). Pass--allow-system-keysto opt in – this lets you drive a global hotkey such as PowerToys'win+shift+vorwin+r(the global low-level hook watches the OS-wide input stream, so the injected combo fires it). Ausnahmen, die auch bei--allow-system-keysblockiert bleiben:win+lSperrt die Arbeitsstation, überLockWorkStation()die die Automatisierung nicht wiederhergestellt werden kann (bricht CI- und Remotedesktopsitzungen), undctrl+alt+delist eine sichere Aufmerksamkeitssequenz (SAS), die Windows von injizierten Eingaben unabhängig von der Kennzeichnung abbricht – es kann nie wirksam werden, sodass fehler (invalid_arguments, Beenden 1) und kein irreführender Erfolg gemeldet werden. Andere Kombinationen (alt+f4,ctrl+shift+esc,win+r, ...) werden mit der Kennzeichnung zugelassen – Anrufer-Beware. Alternativ können Sie eine Systemkombination für eine bestimmte Fensterverwendung--via post-messagebereitstellen, die fensterbereichsgeschützt und nicht betroffen ist (ein geposteteswin+lElement ist jedoch unbedenklich, obwohl ein gepostetesalt+f4Fenster weiterhin das Zielfenster schließt).
Ereignisse pro Tastenkombination (KeyDown / TextChanged):
-
Benannte Schlüssel und Modifiziererkombinationen (
down, ,enterctrl+shift+tvk=0xNN, ) auslösen ein realesKeyDown(undKeyUp) auf beiden Transporten – sie werden als diskreteWM_KEYDOWN/WM_KEYUP(oderSendInputvirtuelle Schlüsselereignisse) übermittelt. -
Literal typisierter Text (
hello) unterscheidet sich je nach Transport:-
--via send-inputordnet jedes Zeichen seiner virtuellen Taste (plus Umschalt) im aktiven Tastaturlayout zu, sodass das Ziel eine OriginalversionKeyDownmit der richtigen virtuellen Taste sieht, gefolgt von der vom Betriebssystem verfasstenWM_CHAR(AnhebungTextChanged) – d. h. einem vollständigen Tastenanschlag pro Zeichen. Zeichen, die im aktuellen Layout nicht erreichbar sind (oder STRG/AltGr benötigen), greifen auf ein Unicode-Paket zurück, sodass das genaue Zeichen weiterhin landet. Verwenden Siesend-inputdiese Option, wenn Sie die Genauigkeit pro TastenanschlägeKeyDownbenötigen (z. B. fahren Sie eine WinUI 3 / WPFTextBox, deren Handlern ausgeschaltetKeyDownsind). Für einen normalen (nicht erhöhten) WinUI 3-Testhost bringen Sie das Fenster zuerst in den Vordergrund (winapp ui focus/klicken darauf), dasend-inputdas Vordergrundfenster auf das Vordergrundfenster ausgerichtet ist. -
--via post-messagestellt ein einzelnesWM_CHARZeichen pro Zeichen (es wird nichtWM_KEYDOWN/WM_KEYUPfür eingegebenen Text bereitgestellt , die für benannte Tasten/Kombinationen reserviert sind), wodurch kein Zeichen pro ZeichenKeyDownerhöht wird. Es wird automatisch auf das untergeordnete Steuerelement des Fensters ausgerichtet, sodass klassische Win32/WinForms -gesteuerte BearbeitungssteuerelementeWM_CHARden Text (Auslösen) landenTextChanged. Einschränkung: WinUI 3 / UWP / XAML-Apps (winapps primäres Ziel) verfügen über fensterlose Steuerelemente, die gepostetWM_CHAR/WM_KEYDOWNignoriert werden , also weder Literaltext noch benannte Tasten (Eingabetaste, Ziffern, ...) erreichen sie, auch wenn der Befehl erfolg meldet. Es gibt eine Warnung aus, wenn das Ziel wie XAML aussieht und trotzdem 0 beendet (PostMessagewird ausgelöst und vergessen und kann die Übermittlung nicht bestätigen). Wird--via send-inputverwendet, um WinUI 3 / UWP / WPF-Apps zu steuern; reservierenpost-messageSie für klassische Win32-Steuerelemente oder wenn Sie es nur für Integritätsebenen mit Fensterbereich benötigen.
-
JSON-Ausgabe (--json): Das Ergebnis hwnd ist das effektive Fenster, an das die Schlüssel übermittelt wurden– für --via post-message dies ist das aufgelöste, fokussierte untergeordnete Steuerelement, wenn der Befehl darauf neu ausgerichtet ist (nicht unbedingt das Fenster der obersten Ebene-w/-a/-e), sodass die Automatisierung genau überprüfen kann, wo die Eingabe landet. Wenn dieses effektive Ziel wie ein fensterloser XAML-Host aussieht, wird die obige Übermittlungsbemerkung auch als warnings[] Eintrag angezeigt (die gleiche Empfehlung auf der Konsole), sodass ein ✅ Exit 0 nicht für die bestätigte Zustellung verwechselt wird.
Set-Value
Legen Sie einen Wert für ein bearbeitbares Element programmgesteuert fest (keine Tastaturanschläge, keine App-Vordergrund). Verwendet eine Fallbackkette:
- ValuePattern – TextBox, ComboBox, PasswordBox und die meisten bearbeitbaren Steuerelemente.
- RangeValuePattern – numerische Steuerelemente (Slider, ProgressBar), wenn der Wert als Zahl analysiert wird.
-
LegacyIAccessible (
IAccessible::put_accValue) – der Fallback für TextPattern-only-Bearbeitungssteuerelemente , die keinen ValuePattern (z. B. Rich-Edit/DocumentVerfassen-Felder) verfügbar machen. Dadurch wird die Lese-/Schreiblücke geschlossen, bei derget-valueein solches Steuerelement gelesen werden konnte, aberset-valuenicht.
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
Wenn keins der drei Muster den Wert festlegen kann, schlägt ein eindeutiger Fehler fehl, set-value der als send-keys letzte Möglichkeit zeigt.
Nicht jeder Rich-Editor unterstützt programmgesteuerten Satz. Der LegacyIAccessible-Fallback funktioniert nur für Steuerelemente, deren Barrierefreiheit implementiert wird
IAccessible::put_accValue– systemeigene Win32 Rich-Edit-Steuerelemente und Chromium/Electron/WebView2-Verfassenoberflächen führen in der Regel aus. WinUI 3RichEditBoxund WPFRichTextBoxunterstützen die programmgesteuerte Werteinstellung nicht – sie machen ihre Inhalte so designgesteuert für Benutzeroberflächenautomatisierung als schreibgeschützt verfügbar (Textmuster, kein setierbares Wertmuster), sodassset-valuesie nicht in sie schreiben können. Verwenden Siesend-keysfür diese Benutzer (die einen entsperrten, vordergrundierten Desktop benötigen).
get-value
Lesen Sie den aktuellen Wert aus einem Element. Verwendet eine intelligente Fallbackkette: TextPattern (RichEditBox, Document) → ValuePattern (TextBox, Slider) → SelectionPattern (ComboBox, RadioButton, TabView) → Name (Bezeichnungen).
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
Ein leeres Textfeld wird "text": ""erfolgreich gelesen, nicht die Barrierefreiheitsbezeichnung. Nur Leerzeicheninhalte werden auch in JSON beibehalten.
wait-for --value "" entspricht einem leeren Feld, unabhängig davon, ob es nach der Bearbeitung neu ist oder gelöscht wurde. Verwenden Sie get-property --property Namezum Lesen der Barrierefreiheitsbezeichnung stattdessen .
Fokus
winapp ui focus txt-textbox-a4b1 -a notepad
Aktiviert das Fenster des ausgewählten Steuerelements bei Bedarf, und konzentriert dann das Steuerelement.
Die Auswahl ist erforderlich; verwenden -a <app> oder -w <HWND> wählen Sie das Ziel aus.
Erfolg bedeutet, dass das Fenster vordergrund und das ausgewählte Steuerelement vor der Rückgabe des Befehls bestätigt HasKeyboardFocus wurde. Der Befehl ermöglicht bis zu 500 ms, damit das Steuerelement den Fokus meldet; es wird angehalten, wenn das Ziel verschwindet oder den Vordergrund verliert, anstatt zu versuchen, den Fokus zurückzunehmen. Ein im Besitz befindliches Dialogfeld vor dem Hauptfenster reicht nicht aus: Wählen Sie ein Steuerelement im Dialogfeld aus, wenn dies Ihr Ziel ist.
Dieser Befehl benötigt einen entsperrten, interaktiven Desktop und umgeht nicht Windows Aktivierungseinschränkungen. Wenn dies fehlschlägt foreground_not_target, aktivieren Sie das beabsichtigte Fenster manuell, und suchen Sie vor dem Erneuten Wiederholen nach einem Blockierungsdialogfeld.
focus_not_acquiredPrüfen Sie für die aktuelle Benutzeroberfläche, und wählen Sie ein fokussierbares Steuerelement aus.
Für stale_element, entdecken Sie das Ziel mit inspect oder search.
Behalten Sie dasselbe --on Ziel bei der Ermittlung bei, und wiederholen Sie die Befehle.
Scrollen in die Ansicht
Scrollen Sie ein Element in den sichtbaren Bereich.
winapp ui scroll-into-view itm-targetitem-c3d4 -a myapp
Warten auf
Warten Sie, bis ein Element angezeigt, ausgeblendet oder ein Wert ein Ziel erreicht hat.
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
Scrollen
Scrollen Sie in einem Containerelement. Suchen Sie bildlauffähige Container mit search scroll – suchen Sie nach [scroll:v] (vertikalen) oder [scroll:h] (horizontalen) Markierungen.
# 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
Optionen:
-
--direction <up|down|left|right>— Scrollen Sie inkrementell überScrollPattern. -
--to <top|bottom>— Springe zum Start/Ende überScrollPattern. -
--wheel <notches>— Synthetisieren der Mausradeingabe über die Mitte des Elements überSendInput, in Rad notches (Detents):1= ein Notch nach oben/weg,-1= ein Notch nach unten/richtung,3= drei Notches nach oben. (Jede Klammer ist die WindowsWHEEL_DELTAvon 120 Einheiten, dieSendInputverbraucht werden; die CLI skaliert notches um 120 für Sie.) UmgehungenScrollPattern.
--direction,--tound--wheelschließen sich gegenseitig aus – übergeben Sie genau eine. Da--wheelbetriebssystemweite Eingaben an Bildschirmkoordinaten eingefügt werden, wird das Ziel zuerst in den Vordergrund verschoben und schlägt (foreground_not_target) fehl, wenn der Fokus nicht übertragen werden konnte, anstatt das falsche Fenster zu scrollen.
get-focused
winapp ui get-focused -a myapp
winapp ui get-focused -w <HWND> --json
Zeigen Sie das Element an, das derzeit den Tastaturfokus in der ausgewählten App hat, einschließlich Steuerelementen, deren App-Besitz nur über das übergeordnete Fenster verfügbar ist.
Bei -wdiesem Fenster muss der Fokus gehören, nicht zu einem anderen Fenster oder einem eigenen Popup im selben Prozess. Mit -a, andere Fenster im ausgewählten Prozess sind enthalten.
Die JSON-Ausgabe hat hasFocus:false , wenn kein fokussiertes Element als Zugehörigkeit zum Ziel überprüft werden kann. Wenn eine Fokus- oder Fensterbesitzabfrage fehlschlägt, beendet der Befehl stattdessen nicht den Wert "nonzero". versuchen get-focusedSie es erneut, und entdecken Sie das Fenster erneut, wenn list-windows es geschlossen wurde.
Listenfenster
Auflisten aller sichtbaren Fenster für eine App, einschließlich Popups und Dialogfeldern. Standardmäßig werden unbenannte Fenster mit nuller Größe (unsichtbare Systemfenster) ausgeschlossen.
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
Ertrag
Lassen Sie die Benutzeroberfläche dieses Workflows frühzeitig los, anstatt die Vier-Sekunden-Leerlauf-Gnade auszuwarten. Erfordert ; verwendet WINAPP_UI_WORKFLOW_IDkeine App und keinen Selektor. Sehen Sie sich die frühzeitige Veröffentlichung der Drehung an.
winapp ui yield
winapp ui yield --json # {"released": true} — or false when nothing was held
Frameworkunterstützung
| Rahmenwerk | Überprüfen | search | Aufrufen | Set-Value | Screenshot |
|---|---|---|---|---|---|
| WPF | ✅ Vollständige Struktur | ✅ Alle Eigenschaften | ✅ Alle Muster | ✅ ¹ | ✅ |
| WinForms | ✅ | ✅ | ✅ | ✅ | ✅ |
| Win32 | ✅ | ✅ | ✅ | ✅ | ✅ |
| WinUI 3 | ✅ | ✅ | ✅ | ✅ ¹ | ✅ |
| Elektron | ⚠– Chromium-Struktur | ⚠️ Begrenzt | ⚠– Variiert | ⚠– Variiert | ✅ |
| Flutter | ⚠️ Einfach | ⚠️ Einfach | ❌ Minimal | ❌ | ✅ |
¹ set-value funktioniert für jedes Steuerelement, das ValuePattern/RangeValuePattern verfügbar macht, sowie TextPattern-only Bearbeitungssteuerelemente, deren Barrierefreiheit implementiert IAccessible::put_accValue wird (LegacyIAccessible Fallback).
WinUI 3 RichEditBox und WPF RichTextBox sind Ausnahmen – sie machen nur das schreibgeschützte Textmuster (kein settable Value-Muster) verfügbar, sodass sie nicht programmgesteuert nach Entwurf festgelegt werden können. Verwenden send-keys Sie (interaktiver Desktop erforderlich), um sie einzugeben.
Verwenden des Moduls aus Ihrem eigenen Code
Alles winapp ui ist als Bibliothek verfügbar, sodass Sie die gleiche Automatisierung von einem Test oder Tool aus steuern können, ohne eine Shell für die CLI auszuführen:
| Package | Welchen Mehrwert es bietet |
|---|---|
Microsoft.Windows.SDK.BuildTools.WinApp.UIAutomation |
Inspektion, Selektoren, UIA-Musterinteraktion, Eingabeeinfügung, Screenshots |
Microsoft.Windows.SDK.BuildTools.WinApp.UIAutomation.Recording |
Videoaufzeichnung in MP4 sowie Framepakete |
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);
Verwenden Sie für deterministische Aktionen die Überladung 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 lehnt mehrdeutigen Text ab, anstatt eine beschreibbare Übereinstimmung auszuwählen. Exakte AutomationId-Übereinstimmungen haben Vorrang vor Namen oder AutomationId-Teilzeichenfolgen; Ein eindeutiger Name kann weiterhin ein Steuerelement auswählen, dessen AutomationId freigegeben ist.
Bei einem App-Bereichsziel deckt diese Überprüfung alle App-/eigenen Fenster ab. Verwenden Sie -w <HWND> (oder ein explizites Fensterbibliotheksziel), um den Auswahlbereich einzuschränken.
Es wird zurückgegeben Pattern und PerformedAction mit der gleichen Bedeutung wie das CLI-Aktionsergebnis.
Übergeben Sie ein Element, das von der Inspektion oder Auswahl zurückgegeben wird, wobei die Laufzeits slug oder die eindeutige AutomationId intakt ist. Explizite Aktionen lehnen eine fehlende oder mehrdeutige Identität ab, anstatt nach Name und Steuerelementtyp neu zu binden.
Legen Sie für bereichsbezogene Lesevorgänge UiSelector.Root auf einen anderen UiSelector, ControlType auf einen Typnamen und ClassName auf die Literalanbieterklasse fest. Diese verwenden dieselben Abfrage-Prädikate wie die CLI. Es wird nur eine Stammebene unterstützt: selector.Root.Root muss sein null. Vor dem Nachschlagen des Zielfensters ArgumentException wird ein geschachtelter Stamm ausgelöst. Verwenden Sie eine eindeutige Stammautomatisierungs-ID oder einen Slug anstelle der Verschachtelung von Stammselektoren.
UiControlTypes.GetId(name) löst offizielle Typnamen und die beiden dokumentierten Aliase auf, die 0 für einen ungültigen Namen zurückgegeben werden.
UiControlTypes.GetName(id) gibt den kanonischen Namen oder Unknown(id) für eine nicht erkannte ID zurück.
Behalten Sie beim Übergeben einer UiElement wiederhergestellten Datei von JSON an GetTextAsync oder GetPropertiesAsynchalten Sie die zugehörigen Selector und WindowHandle. Eine Slug-Selektor muss das ursprüngliche Element weiterhin identifizieren; wenn sie nicht mehr vorhanden ist, werden diese Lesevorgänge ausgelöst UiElementNotFoundException , anstatt ein anderes Element mit derselben AutomationId oder demselben Namen auszuwählen. Führen Sie die ursprüngliche Abfrage erneut aus, um das Ergebnis zu aktualisieren. Bereichslesevorgänge verteilen auch Fehler von allgemeinen UIA-Eigenschafts-Gettern und erworbenen UIA-Mustern, anstatt NULL oder einen zuvor erfassten Wert zurückzugeben.
Die Aufzeichnung ist ein separates Paket, sodass Projekte, die nur die Benutzeroberfläche prüfen und steuern, nicht in SkiaSharp abgerufen werden. Das Automatisierungspaket zielt sowohl auf als net10.0-windows10.0.19041.0auch net10.0-windows auf ; letzteres fügt Windows Grafikaufnahme hinzu, was die Erfassung von verdeckten oder GPU-zusammengesetzten windows ermöglichtscreenshot. Sehen Sie sich die README-Datei jedes Pakets auf NuGet für die vollständige API und den Zielframework-Kompromiss an.
UiTarget.FromWindowHandleist der Einstiegspunkt für Testframeworks, die Ihnen bereits ein Fenster übergeben , zMSTest.Windows.UIAutomation. B. ein UIA2AutomationElement, mit MainWindow.Current.NativeWindowHandledem WindowTest.MainWindow Sie überbrücken.
Problembehandlung
| Error | Ursache | Lösung |
|---|---|---|
| "Keine ausgeführte App gefunden" | Nicht ausgeführte App oder nicht übereinstimmende Namen | Überprüfen des Prozessnamens oder Verwenden von PID |
| "Mehrere Fenster übereinstimmen" | Mehrdeutiger -a Wert |
Verwenden -w <HWND> aus den aufgelisteten Optionen |
| "hat mehrere Fenster" | Der Prozess verfügt über mehrere Fenster | Wird -w <HWND> verwendet, um bestimmte Zielwert zu erreichen. |
| "Selector matched N elements" | Mehrdeutige Legacyauswahl | Verwenden von Schrägstrichen aus der inspect Ausgabe oder Anfüge [0][1] an Legacyselektoren |
| "Element hat sich möglicherweise geändert" | Der Slug-Hash stimmt nicht mit dem aktuellen Element überein. | Erneut ausführen inspect oder search neue Slugs erhalten |
| "unterstützt kein Aufrufmuster" | Element kann nicht aufgerufen werden | Verwenden sie inspect für das Element, um ein bestimmbares untergeordnetes Element zu finden |
| "Es wurde kein UIA-Fenster gefunden" | UIA kann den Prozess nicht sehen | Wird list-windows verwendet, um den HWND zu finden, und dann -w |
| "Fenster hat null Größe" | Fenster wird minimiert | Die App wird automatisch wiederhergestellt. |
| Popup/Dropdown nicht im Screenshot | Die Standarderfassung ist pro Fenster und enthält keine nicht verworrenen Überlagerungen. | Folgen Sie dem Screenshot-Überlagerungsworkflow , um ein Fenster mit -w <hwnd> --capture-screen |
von foreground_not_target aus --capture-screen |
Windows die Aktivierung verweigert, sodass eine Bildschirmaufnahme das Fenster aufgezeichnet hätte, das sich tatsächlich im Vordergrund befindet. | Klicken Sie auf das Zielfenster, oder schließen Sie das Fenster "Fokusdiebstahl", und versuchen Sie es erneut, oder legen Sie es ab. --capture-screen |
element_not_found während des Datensatzes |
Selektor angegeben, aber kein übereinstimmende Element | Erneute Ausführung inspect oder search Abrufen einer neuen Auswahl |
| WGC während des Datensatzes nicht verfügbar | Fehler bei der WGC-Erfassung; kein automatisches Fallback | GPU/Treiber überprüfen; Verwendung --capture-screen zur Zustimmung zur Bildschirm-DC-Aufnahme |
Allgemeine Muster
Navigieren und Überprüfen
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
Suchen von Text und Aufrufen des übergeordneten Elements
# 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
Mehrdeutigkeit von doppelten Elementen
winapp ui search '#Image' -a myapp; winapp ui invoke itm-image-a2b3 -a myapp
Screenshot mit Popupüberlagerungen
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
Navigieren, Warten und Überprüfen (einzelne Kette)
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
Entdecken, Klicken und Überprüfen
winapp ui inspect -a myapp --interactive; winapp ui invoke btn-submit-7a90 -a myapp; winapp ui screenshot -a myapp
Interaktion des Dateidialogfelds
Dialogfelder zum Öffnen/Speichern von Dateien sind Standardmäßige dialogfelder Windows mit UIA-Unterstützung:
# 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>
Wird verwendet inspect -w <dialog-hwnd> --interactive , um die tatsächlichen Slugs für ein bestimmtes Dialogfeld zu ermitteln.
Gründe ; für Verkettung (nicht &&)
Der Operator von && PowerShell kann fixieren, wenn eine systemeigene CLI in Stderr schreibt oder ANSI-Escapesequenzen verwendet. Verwenden Sie ; stattdessen – sie führt jeden Befehl bedingungslos aus und vermeidet diesen Deadlock. Dies ist auch für Agentworkflows besser: In der Regel soll der Screenshot ausgeführt werden, auch wenn der Aufruf einen Nicht-Null-Exit hatte.
CI-Testmuster
Verwenden Sie winapp ui-Befehle in CI-Pipelines (GitHub Actions, Azure DevOps) für Rauchtests und ui-Überprüfungen.
wait-for mit --property und --value fungiert als Assertion – es gibt Exitcode 1 beim Timeout zurück, und der CI-Schritt wird automatisch nicht ausgeführt.
Starten und Testen in 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-Elementstatus mit wait-for
wait-for --value abruft, bis der Wert eines Elements mit der erwarteten Zeichenfolge übereinstimmt, wobei derselbe intelligente Fallback verwendet get-value wird (TextPattern → ValuePattern → SelectionPattern → Name). Gibt exit code 0 on match, exit code 1 on timeout - making it a CI-friendly assertion. Verwenden Sie --property diese Option, um stattdessen eine bestimmte UIA-Eigenschaft zu überprüfen.
# 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
Bestätigen mit JSON-Ausgabe
Verwendung --json mit PowerShell oder jq für komplexere Assertionen:
Exit-Code-Vertrag für
searchundwait-forim--jsonModus: Wenn kein Element übereinstimmt (search) oder das Wartezeitlimit (wait-for), schreibt der Befehl einen vollständig analysierten Ergebnisumschlag in stdout ({ "matchCount": 0, ... }oder{ "found": false, "timedOut": true, ... }) und gibt den Ausgangscode 1 zurück. Stderr ist im--jsonModus leer (Loggerausgabe wird unterdrückt). Verzweigung auf den Umschlagfeldern oder von$LASTEXITCODE, je nachdem, welche ergonomischer ist.
# 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" }
Die JSON-Umschläge sind:
-
inspect:{ "depth", "interactive", "hideDisabled", "hideOffscreen", "windows": [...] } -
search:{ "matchCount", "hasMore", "matches": [...] } -
wait-for:{ "found", "waitedMs", "element"?, "timedOut" } -
get-property:{ "elementId", "element", "properties": { ... } }
Eingegebene Elemente verwenden type und numerische x, y, , widthund height.
Geometrie befindet sich in physischen Bildschirmpixeln.
0,0,0,0ist Benutzeroberflächenautomatisierung leere/no-displayed-UI-Rechteck in dieser Projektion; isOffscreen ist getrennt, sodass ein Offscreen-Element weiterhin grenzenlos sein kann.
Jeder inspect --jsonwindows[] Eintrag und das status --json Ergebnis enthalten windowDpi, (windowDpi / 96scale), dpiAwarenessund coordinateSpace: "physical-screen-pixels". Diese beschreiben den DPI-Kontext des Zielfensters, nicht bedingungslos dpi: Windows meldet 96 für ein nicht bekanntes Fenster, System-DPI für ein systemfähiges Fenster und den aktuellen Monitor-DPI für ein monitorfähiges Fenster. Wenn der HWND- oder DPI-Kontext nicht gelesen werden kann, schlägt der Befehl fehl, anstatt 96 automatisch zu ersetzen. Wenn status ein Prozess aufgelöst wird, bevor es über ein Fenster auf oberster Ebene verfügt, werden 0 die DPI-Felder weggelassen, hwnd bis ein Fenster vorhanden ist. Bei prozessweiten inspectVorgängen bleibt das ausgewählte Zielfenster nicht schnell. Wenn ein späteres Popup nach dem Lesen der Struktur ausgeblendet wird, werden die DPI-Felder durch den windows[] Eintrag beibehalten dpiError und weggelassen, während die verbleibenden Fensterstrukturen noch zurückgegeben werden.
Sehen Sie sich die gelieferten winapp-ui-automation Fähigkeiten references/ui-json-envelope.md an, um vollständige Beispiele für jeden Umschlag zu finden.
Vollständiges Rauchtestbeispiel
# 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