Automazione dell'interfaccia utente

Esaminare e interagire con l'esecuzione di applicazioni Windows dalla riga di comando. Usato dagli agenti di intelligenza artificiale e dagli sviluppatori per i test, il debug e l'automazione dell'interfaccia utente.

Overview

winapp ui fornisce comandi per l'ispezione e l'interazione con le interfacce utente dell'app Windows. Usa Windows Automazione interfaccia utente (UIA). Funziona con qualsiasi app Windows: macchine virtuali Windows, WinForms, Win32, Electron e WinUI 3. La maggior parte dei comandi guida l'app tramite modelli di interfaccia utente (senza inserimento di input). Le eccezioni inserisce l'input reale: ui click/ui hoverui drag/usare la simulazione del mouse,/ui touchui pen sintetizzare l'input tocco e penna/stilo e ui send-keys sintetizzare l'input della tastiera, per i controlli e gli scenari che i modelli di interfaccia utente non possono guidare.

Important

Requisito del desktop interattivo (verbi di inserimento di input).click , hover, , pendragtouch, , scroll --wheel, e send-keys --via send-input sintetizzano l'input a livello di sistema operativo, quindi è necessario un desktop interattivo sbloccato e interattivo con la finestra di destinazione in primo piano. In una workstation bloccata o in un desktop protetto (LogonUI/UAC) non possono inserire e non riuscire rapidamente no_interactive_desktop (distinti dai casi di elevazione/foreground_not_target elevazione). touch / pen rifiutare inoltre quando non viene risolta alcuna finestra (no_target); una coordinata all'esterno della finestra di destinazione è un avviso non irreversibile (una warnings[] voce in --jsono una riga di avviso in modalità testo) e l'inserimento continua, coerente con i verbi del mouse. Tutto il resto, inspect, get-propertyset-valuesearchinvokewait-forget-value, scroll --direction/--toscreenshot determina l'app tramite modelli di interfaccia utente ed è compatibile con la sessione headless/bloccata. Preferisce i verbi uiA-pattern in CI; riservare i verbi di inserimento per scenari che effettivamente necessitano di input reale. Prima di inserire, i verbi di movimento risolvono anche l'elemento di destinazione e rifiutano target_moved se è ancora in fase di animazione/rilocazione, anziché l'input di atterraggio su uno spazio vuoto.

Avvio rapido

# 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

Selezione di app di destinazione

In base al nome del processo

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

In base al titolo della finestra

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

Da PID

winapp ui inspect -a 12345

Da HWND (stabile — sopravvive alle modifiche di tabulazioni/titolo)

# 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

Usare -a per l'individuazione, -w per la destinazione stabile. Quando -a corrisponde a più finestre, il comando li elenca con HWND da selezionare.

Selettori

Elementi di destinazione che usano il selettore visualizzato in nell'output [brackets] di ispezione/ricerca. Esistono tre tipi di selettori:

Selettore Meaning Example
MinimizeButton AutomationId (visualizzato quando univoco, stabile, preferito) winapp ui invoke MinimizeButton -a myapp
btn-close-d1a0 Slug semantico (visualizzato quando non è univoco AutomationId) winapp ui invoke btn-close-d1a0 -a myapp
Submit Ricerca in testo normale in Nome/AutomationId (sottostringa senza distinzione tra maiuscole e minuscole) winapp ui invoke Submit -a myapp

I selettori AutomationId sono identificatori del set di sviluppatori (AutomationProperties.AutomationId in XAML). Quando un AutomationId è univoco nell'intero albero inspect dell'interfaccia utente e search lo mostra direttamente come selettore, che sopravvive alle modifiche di layout, alla localizzazione e alla ristrutturazione dell'albero.

I selettori slug (ad esempio, btn-close-d1a0) vengono generati quando non esiste un AutomationId univoco. Formato: prefix-name-hash. L'hash convalida l'identità dell'elemento, ma potrebbe non essere aggiornata dopo le modifiche dell'interfaccia utente.

Esaminare il formato di output

Il inspect comando mostra l'albero degli elementi con output colorato (selettore in ciano, nome in verde, metadati in grigio):

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

La prima parola in ogni riga è il selettore, usarla con altri ui comandi. Quando un elemento ha un automationId univoco, viene usato direttamente (ad esempio, TabView, NewTabButton). Quando non esiste alcun AutomationId univoco, viene usato un slug generato ,ad esempio tab-newtab-5f5b.

Slug semantici

I slugs usano il formato: dove: prefix-normalizedname-hash

  • prefisso — abbreviazione di tipo 3 lettere (btn, txt, chk, cmb, itm, tab, img, lbl, pn, win, grp, lnk, mnu e così via)
  • normalizedname : alfanumerico minuscolo da AutomationId (preferito) o Nome, massimo 15 caratteri
  • hash : hash esadecimale a 4 caratteri del RuntimeId dell'elemento (convalida l'identità dell'elemento)

I slug sono indipendenti dalla shell (senza caratteri speciali), univoci e possono essere usati direttamente come argomenti. L'hash fornisce il rilevamento di decadimento: se l'elemento è stato sostituito, si ottiene: "L'elemento potrebbe essere stato modificato. Eseguire di rieseguare l'ispezione."

Gli elementi senza nome o AutomationId mostrano solo il prefisso + hash (ad esempio, pn-c8a3).

Disambiguare più corrispondenze

I slugs dall'output inspect/search sono univoci, ma possono cambiare le modifiche di layout: usarle su nomi di tipo normale o testo quando più corrispondenze. Quando un selettore è ambiguo, l'interfaccia della riga di comando stampa tutte le corrispondenze con i relativi slug, in modo da poter scegliere quella corretta e rieseguerla con tale slug.

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

Usare il testo normale per cercare elementi: non è necessaria una sintassi speciale:

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

Quando una ricerca di testo corrisponde a più elementi (ad esempio, SettingsExpander dove Group, Button e Text condividono lo stesso nome), l'interfaccia della riga di comando seleziona automaticamente l'unico elemento richiamabile. Se più sono richiamabili, elenca tutte le corrispondenze con i slug.

Per i risultati di ricerca non richiamabili (ad esempio, textBlock all'interno di un pulsante), la ricerca espone automaticamente il predecessore richiamabile più vicino, ovvero l'elemento padre che è possibile usare con invoke. Questa operazione funziona per tutti i selettori di ricerca:

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

Il selettore di superficie può essere usato direttamente:

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

Comandi

stato

Connettersi a un'app e visualizzare le informazioni di connessione.

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

Ispezionare

Visualizzare l'albero degli elementi dell'interfaccia utente. L'output mostra i slug semantici con rientro a 2 spazi per la gerarchia:

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

Output di esempio (impostazione predefinita):

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)

Output di esempio ( —--interactive solo elementi richiamabili, elenco flat):

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)

Gli elementi possono mostrare questi marcatori di stato:

  • [on] / [off] / [indeterminate] — Stato attiva/disattiva/casella di controllo
  • [collapsed] / [expanded] — espandere/comprimere lo stato per alberi, caselle combinate, voci di menu
  • [scroll:v] / [scroll:h] / [scroll:vh] — contenitore scorrevole (verticale, orizzontale o entrambi)
  • [offscreen] — l'elemento non è visibile sullo schermo
  • [disabled] — l'elemento non è abilitato
  • value="..." — contenuto di testo corrente per gli elementi modificabili (se diverso da Name)

Trovare elementi corrispondenti a un selettore. L'output mostra i slug semantici:

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

Output di esempio:

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

I slug visualizzati nell'output (ad esempio , btn-minimize-d1a0) possono essere usati direttamente con altri comandi:

winapp ui invoke btn-minimize-d1a0 -a notepad

get-property

Legge i valori delle proprietà da un elemento. Include lo stato specifico del criterio (ToggleState, Value, IsSelected e così via).

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

schermata

Acquisire una finestra o un elemento come PNG. Quando esistono più finestre (ad esempio, finestra di dialogo app + aperta), vengono composte in un singolo PNG con ogni finestra in cui è stato creato un punto.

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)

Quando le finestre di dialogo o i popup sono aperte, tutte le finestre vengono composte in un file PNG, in modo da visualizzare lo stato completo dell'interfaccia utente in un'unica immagine.

Il percorso di acquisizione predefinito usa Windows. Graphics.Capture (WGC), leggendo la superficie composita DWM effettiva, mantenendo angoli arrotondati, trasparenza e funzionamento anche mentre la finestra è bloccata da altri windows. Se WGC non è disponibile (versioni precedenti Windows build) l'interfaccia della riga di comando esegue il fallback a PrintWindow.

Usare --capture-screen quando è necessario acquisire menu popup, elenchi a discesa, riquadri a comparsa o sovrimpressioni di descrizioni comando che non sono di proprietà della finestra di destinazione. --capture-screen legge dal controller di dominio dello schermo e porta prima la finestra in primo piano. Usa --focus se vuoi solo mettere in primo piano la finestra senza cambiare modalità di acquisizione (ad esempio, per garantire che lo screenshot corrisponda a quello che l'utente sta attualmente esaminando).

registro

Registrare la finestra di destinazione (o l'area di un elemento) in un video H.264 MP4. I fotogrammi vengono acquisiti tramite Windows Acquisizione grafica (con fallback PrintWindow/screen-DC) e codificati in modo incrementale con Media Foundation, quindi le registrazioni non memorizzano mai nel buffer il video completo in memoria.

Comportamento predefinito (--duration-sec 0): registra fino all'arresto. Usare CTRL+C in modo interattivo oppure (per i chiamanti programmatici/agenti) scrivere una nuova riga in stdin o chiudere stdin per arrestare e finalizzare correttamente MP4. Un MP4 valido e riproducibile viene sempre finalizzato a qualsiasi arresto normale, senza danneggiamento.

# Timed: record for 10 s at 15 fps
winapp ui record -a myapp --duration-sec 10 --fps 15 --output demo.mp4

# Unbounded (default): record until Ctrl+C, downscaled to max 1280px longest edge
winapp ui record -a myapp --max-edge 1280 --output capture.mp4

# Programmatic stop (agent/script): pipe a newline; the recorder stops and writes a valid MP4
"" | winapp ui record -a myapp --json --output capture.mp4

# Record a single element's region (fails with element_not_found if the selector doesn't match)
winapp ui record itm-chart-9f8e -a myapp --output chart.mp4

# Include screen overlays / popups (captures from screen DC; brings window to foreground)
winapp ui record -a myapp --capture-screen --duration-sec 5 --output with-popups.mp4

Opzioni:

  • --duration-sec N — Record per N secondi. Valore predefinito 0 = record fino all'arresto.
  • --fps N — Fotogrammi di destinazione al secondo (impostazione predefinita 15).
  • --max-edge N — Ridimensionamento in modo che il bordo più lungo sia al massimo N pixel (0 = nessuna riduzione).
  • --capture-screen - Acquisizione dal controller di dominio dello schermo (include sovrimpressioni/popup; in primo piano la finestra).
  • --output <path> — Percorso MP4 di output. Il valore predefinito è recording-<timestamp>-<guid>.mp4 nella directory corrente.

Meccanismi di arresto:

  • Interattivo: CTRL+C (qualsiasi piattaforma).
  • Programmatic/agent: scrivere una nuova riga ("") o chiudere stdin (EOF). L'arresto viene applicato non appena il codificatore è pronto (primo fotogramma acquisito); qualsiasi segnale di arresto che arriva prima che il primo fotogramma venga latch e applicato immediatamente all'idoneità , non c'è alcuna finestra di tolleranza e nessun ritardo del muro.

Modalità di acquisizione (segnalata nel campo JSON mode ):

  • wgc— Windows Acquisizione grafica (impostazione predefinita; funziona mentre la finestra è bloccata).
  • printwindow — GDI PrintWindow (fallback quando WGC non è disponibile in questo sistema/sessione; esegui nuovamente con --capture-screen per usare il controller di dominio dello schermo).
  • screen — Controller di dominio dello schermo tramite --capture-screen (include sovrimpressioni/popup; porta la finestra in primo piano).

Output JSON (--json):

  • stdout (risultato finale): { "path", "frames", "width", "height", "fileSize", "codec": "h264", "mode", "fps", "durationSec" }
  • stderr (evento di liveness, generato all'inizio dell'acquisizione): { "event": "recording-started", "path", "fps", "durationSec" }

L'evento di liveness in stderr consente ai chiamanti programmatici di sapere che il ciclo di acquisizione è attivo senza attendere il risultato finale. Il risultato finale JSON in stdout è un singolo oggetto pulito.

Codici di errore:

  • element_not_found — Selettore specificato ma non trovato alcun elemento corrispondente; ha esito negativo immediatamente (nessun file parziale scritto).
  • ambiguous_selector — Un selettore di testo normale corrisponde a più elementi; usare un slug dai suggerimenti visualizzati nell'errore (o dall'output inspect ) per specificare come destinazione un elemento specifico.
  • invalid_arguments — Valore dell'opzione non valido (ad esempio, --duration-sec -1 o > 86400).

Limitazione nota : popup con finestra: Quando si registra un elemento specifico (tramite selettore) che si trova all'interno di un popup che esegue il rendering nella propria finestra di primo livello, ad esempio un riquadro a comparsa WinUI/XAML, una descrizione comando, una descrizione comando o un menu (Xaml_WindowedPopupClass) , il registratore può acquisire la finestra principale sottostante anziché il popup, producendo frame vuoti o non aggiornati. Registrare l'intera finestra (omettere il selettore) o usare winapp ui screenshot --capture-screen per i popup. Rilevato nel numero 646.

Attivare a livello di codice un elemento (fare clic sul pulsante, attivare o disattivare la casella di controllo, espandere la casella combinata).

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

Prova i criteri in ordine: InvokePattern → TogglePattern → SelectionItemPattern → ExpandCollapsePattern.

click

Fare clic su un elemento in corrispondenza delle coordinate dello schermo usando la simulazione del mouse. Usare questa opzione per i controlli che non supportano InvokePattern (ad esempio, intestazioni di colonna, voci di elenco).

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

Come gli altri verbi di inserimento di input, click porta la destinazione in primo piano e non riesce veloce (no_interactive_desktop su un desktop bloccato/sicuro, foreground_not_target se non è stato possibile trasferire lo stato attivo) anziché fare clic sulla finestra sbagliata. Risolve anche di nuovo l'elemento poco prima del pulsante giù: dopo aver posizionato il cursore esegue un controllo finale della posizione, quindi una destinazione di spostamento/animazione continua non riesce con target_moved anziché segnalare l'esito positivo dopo che il clic è atterrato su uno spazio vuoto. Un esito positivo segnalato indica che la destinazione era ancora in posizione quando il pulsante è andato giù.

Resistenza

Premere il pulsante del mouse in un punto, spostarsi in un altro, quindi rilasciare con drag <from> <to>, dove ogni endpoint è un selettore di elementi (trascina da/al centro dell'elemento) o coordinate x,ydello schermo esattamente come segnalato da winapp ui inspect. Combinare e abbinare liberamente (selettore→selector, selettore→coord, coords→coords).

Usa con spostamenti SendInput intermedi in modo che l'app veda un flusso realistico di WM_MOUSEMOVE messaggi. Usarlo per riordinare/ridimensionare handle, dispositivi di scorrimento, disegno canvas e trascinamento della selezione.

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

Opzioni:

  • --right - Trascinare con il pulsante destro del mouse invece del pulsante sinistro.
  • --hold-ms <ms> — Tenere premuto il pulsante all'inizio prima di spostarsi (impostazione predefinita: 0). Con <from> == <to> (nessun movimento) esegue un movimento di pressione e blocco /pressione prolungata .
  • --dwell-ms <ms> — Attesa nella destinazione dopo lo spostamento, prima del rilascio (impostazione predefinita: 0). Consente di eliminare le destinazioni o unire sovrapposizioni che il braccio da un passaggio del mouse sostenuto (anziché l'istante in cui arriva il cursore) prima del pulsante su.

x,y Le barre sono coordinate dello schermo nello stesso report dello spazio winapp ui inspect/search e un selettore si risolve al centro dell'elemento, ispezionando prima di tutto i punti di selezione.

Come send-keys --via send-input, drag inserisce a livello di sistema operativo le coordinate dello schermo dopo aver portato la destinazione in primo piano. Se lo stato attivo non può essere portato alla destinazione (ad esempio, la prevenzione del furto dello stato attivo da un processo in background), il comando non riesce (foreground_not_target) anziché trascinare sulla finestra sbagliata, ovvero lo stato attivo o fare clic prima sulla finestra. In un desktop bloccato/protetto ha esito negativo con no_interactive_desktop. Ogni endpoint dell'elemento viene risolto immediatamente prima del trascinamento; se è ancora in movimento/ridimensionamento (destinazione di animazione), il comando ha esito negativo e target_moved non viene trascinato in un punto non aggiornato. Gli endpoint bare x,y non possono essere verificati nuovamente, quindi vengono usati as-is.

Toccare

Inserire movimenti di tocco sintetici usando l'API Windows puntatore injection. L'ancoraggio di contatto è un selettore di elementi (usa il centro dell'elemento) o una coordinata x,ydello schermo esplicita tramite --at (stessi report sullo spaziowinapp ui inspect). Usarlo per interazioni con tocco/pressione e movimenti multitocco che la simulazione del mouse non può esprimere.

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)

Opzioni:

  • --gesture <g>tap (impostazione predefinita), double-tap, long-pressswipe, pinch, , stretch.
  • --at <x,y> — Punto iniziale esplicito (coordinate dello schermo). Il valore predefinito è il centro elementi del selettore.
  • --to-point <x,y> — Punto finale per un oggetto swipe. Ha la precedenza su --direction.
  • --direction <right|left|up|down> — Direzione scorrimento rapido (impostazione predefinita: right). Combinato con --distance per calcolare l'endpoint quando --to-point non viene specificato.
  • --distance <px> : distribuitura di dita per pinch/stretcho distanza di scorrimento rapido in pixel.
  • --hold-ms <ms> — Tenere premuti i contatti prima dell'lifting (tempo di attesa con pressione prolungata; il valore predefinito è 500 ms quando long-press non è impostato).
  • --duration-ms <ms> — Tempo di scorrimento per i movimenti mobili (scorrimento rapido/avvicinamento/tratto; valore predefinito 300).
  • --fingers <n> — Numero di contatti (1-10; valore predefinito 1). pinch / stretch usare sempre 2.

Sicurezza dell'iniezione. touch rifiuta l'inserimento a meno che non venga risolto un handle di finestra di destinazione diverso da zero e che tale finestra contenga il primo piano. L'operazione ha esito negativo quando no_target non è possibile risolvere nessuna finestra, foreground_not_target se non è stato possibile trasferire lo stato attivo o no_interactive_desktop su un desktop bloccato/protetto. Ogni coordinata (centro degli elementi, punti di direzione espliciti --at/--to-pointe generati) viene controllata sul rettangolo della finestra di destinazione. Un punto all'esterno della finestra viene esposto come avviso non irreversibile (una warnings[] voce in --jsono una riga di avviso in modalità testo) e l'inserimento continua a corrispondere ai verbi del mouse (drag/scrollclick/hover/), che vengono inseriti anche in coordinate fuori finestra. --fingers sopra 10 viene rifiutato in anticipo.

Nota hardware. Il tocco preferisce il dispositivo di puntatore sintetico moderno (CreateSyntheticPointerDevice(PT_TOUCH)) ed esegue il fallback all'API legacy/InitializeTouchInjectionInjectTouchInput. Se l'inserimento non è supportato nel dispositivo/sessione corrente, il comando visualizza il codice di errore Win32 effettivo (ad esempio "non supportato") anziché segnalare un falso esito positivo, considerare un'uscita non zero come "tocco non recapitato".

sessioni Desktop remoto/VM. In una Desktop remoto (RDP) o in alcune sessioni di macchine virtuali il sistema operativo può accettare il tocco sintetico (uscita 0) senza raggiungere effettivamente l'app di destinazione. Quando viene rilevata una sessione remota, touch aggiunge un avviso di incertezza sul recapito , ovvero una warnings[] voce in --jsono una riga di avviso in modalità testo. Un ✅/exit 0 indica quindi che la chiamata di inserimento ha avuto esito positivo, non che l'app abbia ricevuto l'input; confermare l'effetto con ui screenshot/ui inspect quando è importante.

penna

Inserire input penna/stilo sintetico — tocco e tratti input penna — usando l'API Windows puntatore sintetico (CreateSyntheticPointerDevice(PT_PEN); Windows 10 1809+). Scegliere come destinazione un centro elementi, un punto esplicito --at o un tratto input penna completo --path .

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

Opzioni:

  • --at <x,y> — Punto di contatto penna (coordinate dello schermo). Il valore predefinito è il centro elementi del selettore. Ignorato quando --path viene specificato.
  • --path "<x,y x,y …>" — Percorso tratto input penna come coppie separate da x,y spazi vuoti (un percorso a un punto è un tocco).
  • --pressure <0.0–1.0> — Pressione penna (impostazione predefinita 0,5).
  • --tilt-x <deg> / --tilt-y <deg> — Angoli di inclinazione della penna, da −90 a 90 (impostazione predefinita 0).
  • --eraser — Utilizzare la parte finale della penna invece della punta.
  • --duration-ms <ms> — Tempo totale di spostamento del tratto in millisecondi distribuito come fotogrammi UPDATE interpolati nel percorso (impostazione predefinita: ~10 ms per waypoint). Usare questa opzione per controllare la velocità con cui la penna si sposta visibilmente dall'inizio alla fine.

Sicurezza dell'iniezione. Come touch, pen rifiuta di inserire senza una finestra di destinazione in primo piano () in primo piano (no_target / foreground_not_targetno_interactive_desktop / ) e controlla ogni punto input penna sul rettangolo della finestra di destinazione, visualizzando qualsiasi coordinata fuori finestra come avviso non irreversibile (warnings[] in o una --jsonriga di avviso in modalità testo) pur continuando a inserire , coerente con i verbi del mouse. Non valido --pressure (all'esterno di 0,0-1,0) o inclinazione (all'esterno di ±90°) viene rifiutato in primo piano.

sessioni Desktop remoto/VM. Il routing penna è particolarmente inaffidabile in Desktop remoto: la chiamata injection può segnalare l'esito positivo (uscita 0) mentre nessun input penna raggiunge l'app. Quando viene rilevata una sessione remota, pen aggiunge un avviso di incertezza del recapito (warnings[] in --jsono una riga di avviso in modalità testo) in modo che non ✅ venga erroneamente eseguito un errore per il recapito confermato. Convalidare i flussi dipendenti dalla penna in un desktop interattivo locale.

passaggio del mouse

Spostare il mouse al centro di un elemento per attivare effetti al passaggio del mouse (descrizioni comando, riquadri a comparsa, stati di visualizzazione). SendInput Usa per lo spostamento realistico del mouse con una piccola pulsazione, quindi attende un tempo di attesa configurabile.

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

Opzioni:

  • --dwell-time <ms> — Tempo in millisecondi di attesa dopo il passaggio del mouse per visualizzare gli effetti (impostazione predefinita: 800, intervallo: 0-10000)

send-keys

Inviare l'input della tastiera sintetica, ovvero la controparte della tastiera a click. L'interfaccia utente non ha un modello di iniezione da tastiera, quindi questo scende al livello Win32. Usarlo per lo spostamento tramite tastiera (frecce, TAB, INVIO, ESC), tasti di scelta rapida (ctrl+c, alt+f4) e digitazione nei controlli che richiedono eventi per sequenza di tasti anziché set-valuela scrittura atomica.

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

Grammatica della chiave (token separati da spazi vuoti, virgolette stringhe multi-token):

  • Chiavi denominate : enter/return, escbackspaceescape/spacetab,del/delete , insert, home,/pagedownpageupend/pgdnpgup , ,down//f1/leftupf16appsright , . capslockprintscreen
  • Sequenze : vengono premuti più token nell'ordine: down down enter.
  • Combinazioni di modifica - ctrl, shift, alt, unite win con +: ctrl+shift+t, alt+f4.
  • Testo letterale : qualsiasi token che non è una chiave nota è tipizzato in base al carattere: hello. Le parole letterali adiacenti mantengono lo spazio tra di esse, quindi una frase tra virgolette come "Hello world" è tipizzata verbatim (lo spazio viene mantenuto); un valore letterale che contiene + semplicemente come C++ testo o a+b viene digitato come testo, non analizzato come combinazione.
  • Escape letterale esplicito : anteporre un token a text= per digitarlo verbatim anche quando si scontra con un nome di chiave o modificatore: text=enter digita la parola "invio" anziché premere INVIO e text=ctrl+a digita la stringa letterale. Rispecchia l'escape vk= ; il valore preceduto da escape continuerà a fondersi con parole letterali adiacenti (text=down low → "down low"). Poiché i token sono separati da spazi vuoti (e i valori letterali adiacenti vengono ricreati con un singolo spazio), usare escape barra rovesciata all'interno di un text= valore per digitare spazi vuoti che altrimenti non sopravvivono: \s → spazio, \t tabulazione →, \n → nuova riga, \r → nuova riga, \\ → barra rovesciata letterale. \n, \re \r\n ogni inserisce una singola interruzione di riga (invio / VK_RETURN), quindi text=line1\nline2 e text=line1\r\nline2 entrambi digitano una nuova riga. Quindi text=a\s\sb digita "a b" (spazio doppio) e text=\shi mantiene uno spazio iniziale. Un escape non riconosciuto ,ad esempio \x, viene lasciato verbatim.
  • Valore letterale dell'intero argomento (--verbatim): quando l'intero payload è testo letterale, passare --verbatim anziché eseguire l'escape di ogni token con text=. Digita l'intero argomento chiavi esattamente come specificato , senza interpretazione denominata chiave/combinata/vk=/text= e, a differenza del percorso normale, mantiene gli spazi vuoti interni esatti (senza compressione) senza bisogno di .\s Quindi send-keys "down down enter" --verbatim digita le parole e send-keys "a b" --verbatim mantiene lo spazio doppio. Le sequenze di escape della barra rovesciata non vengono decodificate in --verbatim modalità (un \s oggetto viene digitato come barra rovesciata e "s"). Usare un token quando è necessario un text= carattere di controllo di escape.
  • Chiavi virtuali non elaborate : vk=0xNN (esadecimale) o vk=NN (decimale) per le chiavi senza un nome descrittivo.

Opzioni:

  • --target <selector> — Concentrarsi su questo elemento (tramite UIA) prima di inviare i tasti. Senza di esso, le chiavi passano all'elemento attualmente attivo dell'app.
  • --verbatim — Digitare l'intero argomento chiavi come testo letterale (nessuna chiave/combinata/vk=/text= analisi) e mantenere lo spazio vuoto esatto. Forma di argomento intero dell'escape per token text= .
  • --via <transport>post-message (impostazione predefinita) inserisceWM_CHARWM_KEYDOWN/WM_KEYUP/nella coda della finestra di destinazione. È destinato a HWND e ignora uiPI (funziona tra i livelli di integrità). send-input inserisce il sistema operativo a livello di sistema operativo tramite SendInput e passa alla finestra in primo piano.

Scelta di un trasporto/limiti noti:

  • post-message è l'impostazione predefinita perché ignora uiPI e non dipende dalla finestra in primo piano. Limiti: non è possibile attivare i tasti di scelta rapida globali registrati tramite WH_KEYBOARD_LL hook di basso livello (quelli che toccano l'input upstream di qualsiasi coda di finestre) e le app che leggono lo stato della chiave non elaborata tramite GetAsyncKeyState potrebbero non osservare modificatori mantenuti. Risolve e invia automaticamente alla finestra figlio attiva del thread di destinazione (tramite GetGUIThreadInfo) dopo la creazione in primo piano, quindi le app Win32/WinForms classiche i cui controlli sono chiavi di ricezione di finestre figlio separate senza impostare manualmente come destinazione il controllo. Le app WinUI 3/UWP hanno controlli XAML senza finestra senza HWND figlio, quindi un post non WM_CHAR/WM_KEYDOWN ha nulla da inserire e viene eliminato. Il post-messaggio non può guidarli (il comando avvisa e esce da 0); usa --via send-input. (macchine virtuali Windows finestre sono single-HWND e indirizzano le chiavi all'elemento con stato attivo internamente, quindi il post-messaggio funziona lì.
  • send-inputproduce input completamente reale (modificatori visibili a GetAsyncKeyState, attiva hook di basso livello) ma passa a qualsiasi finestra in primo piano e viene bloccato da UIPI quando si inserisce da un processo con privilegi elevati in una destinazione di integrità inferiore (AppContainer/AppX). Se send-input segnala un errore, è probabile che la destinazione sia elevata o un'app AppX, usare post-messageo eseguire l'interfaccia della riga di comando a un livello di integrità corrispondente. Come guardia di sicurezza, send-input verifica che la finestra di destinazione sia in primo piano immediatamente prima dell'inserimento e dell'esito negativo (foreground_not_target) anziché digitare nella finestra sbagliata se non è stato possibile spostarlo sullo stato attivo, ovvero lo stato attivo o fare clic prima sulla finestra. In un desktop bloccato o protetto ha esito negativo con no_interactive_desktop (non esiste alcuna finestra in primo piano per inserire) - sbloccare la sessione o usare un verbo uiA-pattern (set-value, invoke).
  • Le combinazioni riservate dal sistema (win+l, win+r, ctrl+alt+delctrl+shift+esc, , alt+tab, alt+f4, ctrl+esc, lone win/printscreen, ...) agiscono sul sistema operativo/shell anziché solo sulla destinazione quando viene inviato a livello di sistema operativo. send-input li rifiuta per impostazione predefinita (errori con invalid_arguments e non invia nulla) perché l'inserimento a livello del sistema operativo ha effetti ben oltre la finestra di destinazione (ad esempio win+l , blocca la sessione). Passare --allow-system-keys per acconsentire esplicitamente: consente di guidare un tasto di scelta rapida globale, ad esempio PowerToys win+shift+v o win+r (l'hook di basso livello globale controlla il flusso di input a livello di sistema operativo, in modo che la combinazione inserita venga attivata). Eccezioni che rimangono bloccate anche con --allow-system-keys:win+l blocca la workstation tramite LockWorkStation() la quale non è irreversibile dall'automazione (interrompe sessioni CI e desktop remoto) ed ctrl+alt+del è una sequenza di attenzione sicura (SAS) che Windows elimina l'input inserito indipendentemente dal flag , non può mai avere effetto, quindi errori (invalid_arguments, uscita 1) invece di segnalare un esito positivo fuorviante. Altre combinazioni (alt+f4, ctrl+shift+esc, win+r, ...) diventano consentite con il flag : attenzione del chiamante. In alternativa, per recapitare una combinazione di sistema a una finestra specifica usa --via post-message, che è con ambito finestra e non interessato (un post è innocuo, anche se un post win+lalt+f4 chiude ancora la finestra di destinazione).

Eventi per sequenza di tasti (KeyDown/TextChanged):

  • Le chiavi denominate e le combinazioni di modifica (down, enter, ctrl+shift+t, vk=0xNN) generano un reale KeyDown (e KeyUp) su entrambi i trasporti, che vengono recapitati come eventi discreti WM_KEYDOWN/WM_KEYUP (o SendInput di chiave virtuale).
  • Il testo tipizzato letterale (hello) è diverso dal trasporto:
    • --via send-input esegue il mapping di ogni carattere al tasto virtuale (più MAIUSC) nel layout della tastiera attivo, quindi la destinazione vede un autentico KeyDown con il tasto virtuale corretto seguito dal sistema operativo composto WM_CHAR (generando TextChanged) , ovvero una sequenza di tasti completa per carattere. I caratteri non raggiungibili nel layout corrente (o che richiedono CTRL/ALTGR) rebackno a un pacchetto Unicode, in modo che il carattere esatto venga ancora raggiunto. Usa send-input quando hai bisogno di fedeltà per sequenza di tasti KeyDown (ad esempio, guidando un winUI 3 / macchine virtuali Windows TextBox il cui tasto di manipolazione è disattivato KeyDown). Per un host di test WinUI 3 normale (non con privilegi elevati), portare la finestra in primo piano (winapp ui focus / facendo clic su di esso) perché send-input è destinata alla finestra in primo piano.
    • --via post-message inserisce un singolo WM_CHAR carattere ( non inserisce WM_KEYDOWN/WM_KEYUP per il testo tipizzato , ovvero sono riservati per chiavi/combo denominate), che non genera un per carattere KeyDown. Restituisce automaticamente il controllo figlio con lo stato attivo della finestra, quindi i controlli di modifica basati su Win32/WinForms WM_CHARclassici determinano il suolo del testo (generazione TextChanged). Avvertimento: Le app WinUI 3/UWP/XAML (destinazione primaria di winapp) dispongono di controlli senza finestra che ignorano i messaggi pubblicati, quindi il testo letteraleWM_KEYDOWNWM_CHAR/ le chiavi denominate (Invio, cifre, ...) li raggiungono, anche se il comando segnala l'esito positivo. Genera un avviso quando la destinazione è simile a XAML e chiude ancora 0 (PostMessage è attiva e dimentica e non riesce a confermare il recapito). Usa --via send-input per guidare le app WinUI 3/UWP/macchine virtuali Windows; riservare post-message per i controlli Win32 classici o quando è necessaria solo l'ambito finestra tra i livelli di integrità.

Output JSON (--json): il risultato hwnd è la finestra effettiva a cui sono state recapitate le chiavi, perché --via post-message si tratta del controllo figlio con stato attivo risolto quando il comando viene retargetato (non necessariamente la finestra di primo livello-w//-a-e), in modo che l'automazione possa confermare esattamente dove è atterrato l'input. Quando tale destinazione effettiva è simile a un host XAML senza finestra, anche l'avviso di recapito precedente viene visualizzato come voce warnings[] (lo stesso avviso visualizzato nella console), quindi un'uscita ✅ 0 non viene scambiata per il recapito confermato.

set-value

Impostare un valore su un elemento modificabile a livello di codice (nessuna sequenza di tasti, nessuna app in primo piano). Usa una catena di fallback:

  1. ValuePattern : TextBox, ComboBox, PasswordBox e la maggior parte dei controlli modificabili.
  2. RangeValuePattern : controlli numerici (Slider, ProgressBar) quando il valore viene analizzato come numero.
  3. LegacyIAccessible (IAccessible::put_accValue): il fallback per i controlli di modifica solo TextPattern che espongono nessun valorePattern (ad esempio, caselle rich-edit/ Document compose). In questo modo si chiude il gap di lettura/scrittura in cui get-value è possibile leggere un controllo di questo tipo, ma set-value non è stato possibile.
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

Se nessuno dei tre modelli può impostare il valore, set-value ha esito negativo con un errore chiaro che punta all'ultima send-keys risorsa.

Non tutti gli editor avanzati supportano set a livello di codice. Il fallback LegacyIAccessible funziona solo sui controlli la cui accessibilità implementa IAccessible::put_accValue , ovvero controlli di modifica avanzati Win32 nativi e le superfici di composizione Chromium/Electron/WebView2 in genere. WinUI 3 RichEditBox e macchine virtuali Windows RichTextBox non supportano l'impostazione di valori a livello di codice, esponendo il contenuto a Automazione interfaccia utente come di sola lettura (modello di testo, nessun modello valore impostabile), quindi set-value non può scriverli. Usa send-keys (che richiede un desktop in primo piano sbloccato) per quelli.

get-value

Leggere il valore corrente da un elemento . Usa una catena di fallback intelligente: TextPattern (RichEditBox, Document) → ValuePattern (TextBox, Slider) → SelectionPattern (ComboBox, RadioButton, TabView) → Name (etichette).

winapp ui get-value doc-texteditor-53ad -a notepad          # read full document text
winapp ui get-value SearchBox -a myapp                      # read TextBox content
winapp ui get-value CmbTheme -a myapp                       # read ComboBox selected item
winapp ui get-value sld-volume-b2c3 -a myapp                # read Slider value
winapp ui get-value lbl-title-a1b2 -a myapp --json          # JSON: { "elementId": "...", "text": "..." }

focus

Spostare lo stato attivo della tastiera su un elemento.

winapp ui focus txt-textbox-a4b1 -a notepad

scorrimento nella visualizzazione

Scorrere un elemento nell'area visibile.

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

wait-for

Attendere che un elemento venga visualizzato, scomparire o avere un valore raggiunto una destinazione.

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

scorrere

Scorrere un elemento contenitore. Trovare contenitori scorrevoli con search scroll : cercare [scroll:v] indicatori (verticali) o [scroll:h] (orizzontali).

# 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

Opzioni:

  • --direction <up|down|left|right> — Scorrere in modo incrementale tramite ScrollPattern.
  • --to <top|bottom> — Passare all'inizio/fine tramite ScrollPattern.
  • --wheel <notches> — Sintetizzare l'input della rotellina del mouse sul centro dell'elemento tramite SendInput, nelle tacche delle ruote (detents): 1 = una notch up/away, -1 = una notch giù/verso l'alto, 3 = tre tacche su. Ogni tacca è l'Windows WHEEL_DELTA di 120 unità che SendInput utilizza. L'interfaccia della riga di comando ridimensiona automaticamente le prestazioni di 120 unità. ScrollPatternIgnora .

--direction, --toe --wheel si escludono a vicenda : passano esattamente uno. Poiché --wheel inserisce l'input a livello di sistema operativo alle coordinate dello schermo, porta prima la destinazione in primo piano e non riesce (foreground_not_target) se non è stato possibile trasferire lo stato attivo, anziché scorrere la finestra errata.

ottenere l'attenzione

Mostra l'elemento con lo stato attivo della tastiera.

winapp ui get-focused -a myapp

list-windows

Elencare tutte le finestre visibili per un'app, inclusi popup e finestre di dialogo. Per impostazione predefinita, le finestre senza titolo con dimensioni zero (finestre di sistema invisibili) vengono escluse.

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

Supporto del framework

Struttura Ispezionare search evocare set-value schermata
macchine virtuali Windows ✅ Albero completo ✅ Tutte le proprietà ✅ Tutti i modelli ✅ ¹
WinForms
Win32
WinUI 3 ✅ ¹
Elettrone ⚠️ Albero chromium ⚠️ Limitato ⚠️ Varia ⚠️ Varia
Flutter ⚠️ Basic ⚠️ Basic ❌ Minimo

¹ set-value funziona su qualsiasi controllo che espone ValuePattern/RangeValuePattern, oltre ai controlli di modifica solo TextPattern i cui controlli di accessibilità implementano IAccessible::put_accValue (fallback LegacyIAccessible). WinUI 3 RichEditBox e macchine virtuali Windows RichTextBox sono eccezioni: espongono solo il modello Text di sola lettura (nessun modello valore impostabile), quindi non possono essere impostati a livello di codice per progettazione; usare send-keys (desktop interattivo necessario) per digitarli.

Risoluzione dei problemi

Error Motivo Soluzione
"Nessuna app in esecuzione trovata" App non in esecuzione o mancata corrispondenza del nome Controllare il nome del processo o usare PID
"Più finestre corrispondono" Valore ambiguo -a Usare -w <HWND> dalle opzioni elencate
"ha più finestre" Il processo ha più finestre Usare -w <HWND> per specificare come destinazione uno specifico
"Selector matched N elements" Selettore legacy ambiguo Usare i slug dall'output inspect o aggiungere [0], [1] ai selettori legacy
"L'elemento potrebbe essere stato modificato" L'hash slug non corrisponde all'elemento corrente inspect Eseguire nuovamente o search per ottenere nuovi slug
"non supporta alcun modello invoke" Non è possibile richiamare l'elemento Usare inspect sull'elemento per trovare un elemento figlio richiamabile
"Nessuna finestra dell'interfaccia utente trovata" L'interfaccia utente non può visualizzare il processo Usare list-windows per trovare HWND, quindi -w
"La finestra ha dimensioni zero" Finestra ridotta a icona L'app verrà ripristinata automaticamente
Popup/elenco a discesa non incluso nello screenshot L'acquisizione predefinita è per finestra e non include sovrimpressioni non acquisite Usare --capture-screen il flag
element_not_found durante il record Selettore specificato ma nessun elemento corrispondente inspect Eseguire di nuovo o search per ottenere un selettore nuovo
WGC non disponibile durante il record L'acquisizione WGC non è riuscita; nessun fallback invisibile all'utente Controllare GPU/driver; usare --capture-screen per fornire il consenso all'acquisizione screen-DC

Modelli comuni

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

Trovare il testo e richiamarne l'elemento padre

# 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

Disambiguare elementi duplicati

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

Screenshot con sovrimpressioni popup

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

Individuare, fare clic e verificare

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

Interazione del dialogo file

Le finestre di dialogo di apertura/salvataggio dei file sono finestre di dialogo standard Windows con supporto dell'interfaccia utente:

# 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>

Usare inspect -w <dialog-hwnd> --interactive per individuare i slug effettivi per un dialogo specifico.

Perché ; per il concatenamento (non &&)

L'operatore di PowerShell può bloccarsi quando un'interfaccia della && riga di comando nativa scrive in stderr o usa sequenze di escape ANSI. Usare ; invece : esegue ogni comando in modo incondizionato ed evita questo deadlock. Questo è anche meglio per i flussi di lavoro dell'agente: in genere si vuole che lo screenshot venga eseguito anche se l'invoke ha una uscita diversa da zero.

Modelli di test CI

Usare i comandi winapp ui nelle pipeline CI (GitHub Actions, Azure DevOps) per i test di fumo e la convalida dell'interfaccia utente. wait-for con --property e --value funge da asserzione: restituisce il codice di uscita 1 al timeout, con esito negativo del passaggio CI automaticamente.

Avviare e testare 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

Stato dell'elemento Assert con wait-for

wait-for --value esegue il polling fino a quando il valore di un elemento corrisponde alla stringa prevista, usando lo stesso fallback intelligente di get-value (TextPattern → ValuePattern → SelectionPattern → Name). Restituisce il codice di uscita 0 alla corrispondenza, il codice di uscita 1 al timeout, rendendolo un'asserzione compatibile con l'integrazione continua. Usare --property invece per controllare una proprietà UIA specifica.

# 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

Asserzione con output JSON

Usare --json con PowerShell o jq per asserzioni più complesse:

Contratto di codice di uscita per search e wait-for in --json modalità: quando nessun elemento corrisponde (search) o il timeout di attesa (wait-for), il comando scrive una busta dei risultati completamente analizzabile in stdout ({ "matchCount": 0, ... } o { "found": false, "timedOut": true, ... }) e restituisce il codice di uscita 1. Stderr è vuoto in --json modalità (l'output del logger viene eliminato). Diramare i campi della busta, o su $LASTEXITCODE, a seconda del quale è più ergonomico.

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

Esempio di test di fumo completo

# 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