Benutzeroberflächenautomatisierung

Ü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-valuewait-for, set-value, invoke, scroll --direction/--to, - screenshot steuert die App über UIA-Muster und ist headless/locked-session friendly. 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

# 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

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

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. Der Hash stellt die Veraltetkeitserkennung bereit – wenn das Element ersetzt wurde, erhalten Sie Folgendes: "Element hat sich möglicherweise geändert. Prüfung erneut ausführen."

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

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        # invokable elements only, auto-depth 8
winapp ui inspect -a myapp --hide-disabled      # hide disabled elements
winapp ui inspect -a myapp --hide-offscreen     # hide offscreen elements

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 aufrufende 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)

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

Screenshot

Erfassen Sie ein Fenster oder Element als PNG. Wenn mehrere Fenster vorhanden sind (z. B. Das Dialogfeld "App + Öffnen"), werden sie in einem einzelnen PNG-Element mit jedem Fenster zusammengesetzt.

winapp ui screenshot -a notepad                     # saves screenshot.png in cwd
winapp ui screenshot -a notepad --output my.png     # custom filename
winapp ui screenshot -a notepad --json              # returns file path as JSON
winapp ui screenshot -w 131906                      # target specific HWND (+ its dialogs)
winapp ui screenshot txt-searchbox-e5f6 -a myapp          # crop to element bounds
winapp ui screenshot -a myapp --capture-screen      # capture from screen (includes popups/overlays; foregrounds window)
winapp ui screenshot -a myapp --focus               # bring window to foreground first, then capture (default WGC path)

Wenn Dialogfelder oder Popups geöffnet sind, werden alle Fenster in einem PNG zusammengesetzt, sodass Sie den vollständigen UI-Zustand in einem einzelnen Bild sehen können.

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 Option --capture-screen , wenn Sie Popupmenüs, Dropdowns, Flyouts oder QuickInfo-Überlagerungen erfassen müssen, die nicht dem Zielfenster gehören. --capture-screen liest aus dem Bildschirm DC und bringt das Fenster zuerst in den Vordergrund. 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).

Datensatz (record)

Zeichnen Sie ein Fenster oder einen Elementbereich in einem H.264 MP4 auf. Die Aufzeichnung wird standardmäßig bis STRG+C oder für umgeleitete Stdin- oder Neueinleitungen oder EOF fortgesetzt.

# 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 demo.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 auf recording-<timestamp>-<guid>.mp4 festgelegt.
  • --frames — Schreiben Sie zeitstempelte JPEG-Nachweise in <output-name>.frames. Unterstützt 1-30 fps und --max-edge 64-4096 (Standard 1280). Framedaten sind auf 1 GiB begrenzt; der MP4-Vorgang fortgesetzt wird, wenn die Obergrenze erreicht ist.

Agentlesbare Frameartefakte:

demo.mp4
demo.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.

Durch --framesvorhandene MP4- und Framepfade werden nicht ersetzt. Wenn die MP4-Finalisierung fehlschlägt, werden beibehaltene Frames unter <output-name>.frames.partial-*veröffentlicht. Frameartefakte enthalten unverschlüsselte Bildschirminhalte; behandeln Sie sie wie Screenshots oder Videos.

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-screen Bildschirm 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-started Ereignis 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 — Mit --framesdem MP4- oder Frameverzeichnis ist bereits vorhanden.
  • frame_output_failed – Es konnte kein Artefakt beibehalten werden, nachdem die Frameausgabe fehlgeschlagen ist.
  • partial_output — Nur ein Artefakt wurde abgeschlossen; prüfen partialOutput und recoveryHint.

Bekannte Einschränkung: Das Aufzeichnen eines Elements in einem Fensterpopup kann das zugrunde liegende Fenster erfassen. Zeichnen Sie das gesamte Fenster auf, oder verwenden Sie ui screenshot --capture-screenes. Siehe Nr. 646.

Programmgesteuertes Aktivieren eines Elements (Klickschaltfläche, Kontrollkästchen umschalten, Kombinationsfeld erweitern).

winapp ui invoke btn-submit-7a90 -a myapp             # by slug from inspect
winapp ui invoke btn-submit-a1b2 -a myapp  # by slug from inspect/search
winapp ui invoke cmb-sizecombobox-b4c5 -a myapp # expand combo box

Versucht Muster in der Reihenfolge: InvokePattern → TogglePattern → SelectionItemPattern → ExpandCollapsePattern.

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 click wird das Ziel im Vordergrund angezeigt und schlägt schnell (no_interactive_desktop auf einem gesperrten/sicheren Desktop, foreground_not_target wenn 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ägt target_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,y sind Bildschirmkoordinaten im gleichen Raumbericht winapp 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, drag fü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 mit no_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 fehl target_moved , anstatt auf einen veralteten Punkt zu ziehen. (Bare x,y Endpunkte 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 ein swipe. Hat Vorrang vor --direction.
  • --direction <right|left|up|down> — Streifrichtung (Standard: right). Kombiniert mit --distance der Berechnung des Endpunkts, wenn --to-point er nicht angegeben wird.
  • --distance <px> – Fingerbreite für pinch/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, wenn long-press sie 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 / stretch immer 2 verwenden.

Injektionssicherheit. touch verweigert das Einfügen, es sei denn, ein Nicht-Null-Zielfensterziehpunkt wird aufgelöst, und das Fenster enthält den Vordergrund . Es schlägt fehl no_target , wenn kein Fenster aufgelöst werden kann, foreground_not_target wenn der Fokus nicht übertragen werden konnte, oder no_interactive_desktop auf 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 in warnings[]oder eine Warnzeile im Textmodus) angezeigt, und das Einfügevorgang wird weiterhin fortgesetzt – mit den Mausverben (--jsonclick/drag/hover/), die auch bei scroll eingefü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-API InitializeTouchInjection/InjectTouchInput zurü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, touch wird eine Warnung zur Übermittlungsunsicherheit angefügt – ein warnings[] 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 inspect wenn 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 --path angegeben wird.
  • --path "<x,y x,y …>" — Freihandstrichpfad als leerzeichentrennte x,y Paare (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 touchwird pen die 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, pen wird 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 hover btn-info-a1b2 -a myapp; winapp ui screenshot -a myapp --capture-screen  # hover then capture tooltip

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

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-Kombinationenctrl, shift, , altverbunden win mit +: ctrl+shift+t, alt+f4.
  • 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ält C++ oder a+b als 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=enter Gibt das Wort "enter" ein, anstatt die EINGABETASTE zu drücken, und text=ctrl+a gibt die Literalzeichenfolge ein. Spiegelt das vk= 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 eines text= Werts , um Leerzeichen einzugeben, die andernfalls nicht überleben würden: \s → Leerzeichen, \t → Tabstopp, \n → Neueline, \r → Neueinbruch, \\ → Literalrückslass. \n, \rund \r\n fügen Sie jeweils einen einzelnen Zeilenumbruch (ein Eingabetaste / VK_RETURN) ein, und text=line1\nline2text=line1\r\nline2 geben Sie beide eine Neue zeile ein. Gibt also text=a\s\sb "a b" (Doppeltes Leerzeichen) ein und text=\shi behält einen führenden Raum bei. Eine unerkannte Flucht (z. B. \x) bleibt unerkannt.
  • Literal () mit ganzem Argument –--verbatim wenn die gesamte Nutzlast Literaltext ist, übergeben --verbatim Sie anstelle jedes Tokens mit text=. 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 also send-keys "down down enter" --verbatim die Wörter ein, und send-keys "a b" --verbatim behalten Sie den doppelten Abstand bei. Umgekehrte Schrägstriche werden nicht im --verbatim Modus decodiert (ein \s umgekehrter Schrägstrich und ein "s"); verwenden Sie ein text= Token, wenn Sie ein Escapezeichen für ein Steuerelement benötigen.
  • Unformatierte virtuelle Schlüsselvk=0xNN (Hexadezimal) oder vk=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 Token text= .
  • --via <transport>post-message (Standard) Beiträge WM_KEYDOWN/WM_KEYUP/WM_CHAR in der Warteschlange des Zielfensters. Es ist HWND-gezielt und umgeht UIPI (funktioniert über Integritätsstufen hinweg). send-input fügt osweit ein SendInput und wechselt zum Vordergrundfenster.

Auswählen eines Transports/ bekannter Grenzwerte:

  • post-message ist die Standardeinstellung, da uiPI umgangen wird und nicht vom Vordergrundfenster abhängt. Grenzwerte: Es kann keine globalen Hotkeys auslösen, die über WH_KEYBOARD_LL Low-Level-Hooks registriert wurden (diejenigen tippen vor der Eingabe vor einer Fensterwarteschlange), und Apps, die den Unformatierten Schlüsselstatus lesen GetAsyncKeyState , dürfen keine gehaltenen Modifizierer beobachten. Es löst automatisch das untergeordnete Fenster des Zielthreads (über GetGUIThreadInfo) 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 gepostetes WM_CHAR/WM_KEYDOWN Element 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-input erzeugt vollständig reale Eingaben (Modifizierer, die sichtbar sind GetAsyncKeyState, 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. Wenn send-input ein 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-input ob 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 fehl no_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+esclone win/printscreen, ...) wirken auf das Betriebssystem/die Shell und nicht nur auf das Ziel, wenn das Betriebssystem breit gesendet wird. send-input lehnt sie standardmäßig ab (Fehler mit invalid_arguments und sendet nichts), da das Einfügen auf Betriebssystemebene Auswirkungen hat, die weit über das Zielfenster hinausgehen (z. B. win+l würde die Sitzung sperren). Pass --allow-system-keys to opt in – this lets you drive a global hotkey such as PowerToys' win+shift+v or win+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+l Sperrt die Arbeitsstation, über LockWorkStation() die die Automatisierung nicht wiederhergestellt werden kann (bricht CI- und Remotedesktopsitzungen), und ctrl+alt+del ist 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 gepostetes win+l Element ist jedoch unbedenklich, obwohl ein gepostetes alt+f4 Fenster weiterhin das Zielfenster schließt).

Ereignisse pro Tastenkombination (KeyDown / TextChanged):

  • Benannte Schlüssel und Modifiziererkombinationen (down, , enterctrl+shift+tvk=0xNN, ) auslösen ein reales KeyDown (und KeyUp) auf beiden Transporten – sie werden als diskrete WM_KEYDOWN/WM_KEYUP (oder SendInput virtuelle Schlüsselereignisse) übermittelt.
  • Literal typisierter Text (hello) unterscheidet sich je nach Transport:
    • --via send-input ordnet jedes Zeichen seiner virtuellen Taste (plus Umschalt) im aktiven Tastaturlayout zu, sodass das Ziel eine Originalversion KeyDown mit der richtigen virtuellen Taste sieht, gefolgt von der vom Betriebssystem verfassten WM_CHAR (Anhebung TextChanged) – 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 Sie send-input diese Option, wenn Sie die Genauigkeit pro Tastenanschläge KeyDown benötigen (z. B. fahren Sie eine WinUI 3 / WPFTextBox, deren Handlern ausgeschaltet KeyDownsind). Für einen normalen (nicht erhöhten) WinUI 3-Testhost bringen Sie das Fenster zuerst in den Vordergrund (winapp ui focus /klicken darauf), da send-input das Vordergrundfenster auf das Vordergrundfenster ausgerichtet ist.
    • --via post-message stellt ein einzelnes WM_CHAR Zeichen pro Zeichen (es wird nichtWM_KEYDOWN/WM_KEYUP für eingegebenen Text bereitgestellt , die für benannte Tasten/Kombinationen reserviert sind), wodurch kein Zeichen pro Zeichen KeyDownerhöht wird. Es wird automatisch auf das untergeordnete Steuerelement des Fensters ausgerichtet, sodass klassische Win32/WinForms -gesteuerte Bearbeitungssteuerelemente WM_CHARden Text (Auslösen) landen TextChanged. Einschränkung: WinUI 3 / UWP / XAML-Apps (winapps primäres Ziel) verfügen über fensterlose Steuerelemente, die gepostet WM_CHAR/WM_KEYDOWN ignoriert 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 (PostMessage wird ausgelöst und vergessen und kann die Übermittlung nicht bestätigen). Wird --via send-input verwendet, um WinUI 3 / UWP / WPF-Apps zu steuern; reservieren post-message Sie 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:

  1. ValuePattern – TextBox, ComboBox, PasswordBox und die meisten bearbeitbaren Steuerelemente.
  2. RangeValuePattern – numerische Steuerelemente (Slider, ProgressBar), wenn der Wert als Zahl analysiert wird.
  3. LegacyIAccessible (IAccessible::put_accValue) – der Fallback für TextPattern-only-Bearbeitungssteuerelemente , die keinen ValuePattern (z. B. Rich-Edit/ Document Verfassen-Felder) verfügbar machen. Dadurch wird die Lese-/Schreiblücke geschlossen, bei der get-value ein solches Steuerelement gelesen werden konnte, aber set-value nicht.
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 3 RichEditBox und WPF RichTextBox unterstützen die programmgesteuerte Werteinstellung nicht – sie machen ihre Inhalte so designgesteuert für Benutzeroberflächenautomatisierung als schreibgeschützt verfügbar (Textmuster, kein setierbares Wertmuster), sodass set-value sie nicht in sie schreiben können. Verwenden Sie send-keys fü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": "..." }

Fokus

Verschieben des Tastaturfokus auf ein Element.

winapp ui focus txt-textbox-a4b1 -a notepad

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 über ScrollPattern.
  • --to <top|bottom> — Springe zum Start/Ende über ScrollPattern.
  • --wheel <notches> — Synthetisieren der Mausradeingabe über die Mitte des Elements über SendInput, 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 Windows WHEEL_DELTA von 120 Einheiten, die SendInput verbraucht werden; die CLI skaliert notches um 120 für Sie.) Umgehungen ScrollPattern.

--direction, --tound --wheel schließen sich gegenseitig aus – übergeben Sie genau eine. Da --wheel betriebssystemweite 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

Zeigt das Element an, das derzeit den Tastaturfokus besitzt.

winapp ui get-focused -a myapp

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

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.

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. Kennzeichnung verwenden --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

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 set-value txt-searchbox-e5f6 "query" -a myapp; winapp ui screenshot -a myapp --capture-screen
winapp ui invoke btn-settings-a1b2 -a myapp; winapp ui wait-for pn-settingspage-c3d4 -a myapp --timeout 3000; winapp ui screenshot -a myapp -o settings.png

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 search und wait-for im --json Modus: 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 --json Modus 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)" }

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