Otomatisasi Antarmuka Pengguna (UI Automation)

Periksa dan berinteraksi dengan menjalankan aplikasi Windows dari baris perintah. Digunakan oleh agen dan pengembang AI untuk pengujian, penelusuran kesalahan, dan otomatisasi UI.

Ikhtisar

winapp ui menyediakan perintah untuk memeriksa dan berinteraksi dengan UI aplikasi Windows. Menggunakan Windows UI Automation (UIA). Bekerja dengan aplikasi Windows apa pun — WPF, WinForms, Win32, Electron, dan WinUI 3. Sebagian besar perintah mendorong aplikasi melalui pola UIA (tanpa injeksi input). Pengecualian menyuntikkan input nyata: ui click/ui hover/ui dragmenggunakan simulasi mouse,ui touch/ui pen mensintesis sentuhan dan input pena/stylus, dan ui send-keys mensintesis input keyboard — untuk kontrol dan skenario yang tidak dapat didorong oleh pola UIA.

Important

Persyaratan interaktif-desktop (kata kerja input-menyuntikkan).click, , hover, drag, touch, penscroll --wheel, , dan send-keys --via send-input mensintesis input tingkat OS, sehingga mereka memerlukan desktop interaktif yang tidak terkunci dengan jendela target di latar depan. Pada stasiun kerja terkunci atau desktop aman (LogonUI/UAC) mereka tidak dapat menyuntikkan dan gagal dengan cepat dengan no_interactive_desktop (berbeda dari elevasi/foreground_not_target kasus). touch / pen selain itu menolak ketika tidak ada jendela yang menyelesaikan (no_target); koordinat di luar jendela target adalah peringatan non-fatal ( warnings[] entri di bawah --json, atau baris peringatan dalam mode teks) dan injeksi masih berlanjut — konsisten dengan kata kerja mouse. Segala sesuatu yang lain - inspect, , searchget-property, get-value, wait-for, set-value, invoke, scroll --direction/--to, screenshot - mendorong aplikasi melalui pola UIA dan ramah tanpa kepala / sesi terkunci. Lebih suka kata kerja pola UIA di CI; cadangkan kata kerja injeksi untuk skenario yang benar-benar membutuhkan input nyata. Sebelum menyuntikkan, kata kerja gerakan juga menyelesaikan kembali elemen target dan menolak jika target_moved masih meniru/merelokasi, daripada mendaratkan input pada ruang kosong.

Mulai Cepat

# 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

Menargetkan Aplikasi

Menurut nama proses

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

Menurut judul jendela

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

Menurut PID

winapp ui inspect -a 12345

Menurut HWND (stabil — bertahan dari perubahan tab/judul)

# 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

Gunakan -a untuk penemuan, -w untuk penargetan yang stabil. Saat -a cocok dengan beberapa jendela, perintah mencantumkannya dengan HWND untuk Anda pilih.

Selektor

Elemen target menggunakan pemilih yang ditampilkan dalam [brackets] output inspeksi/pencarian. Ada tiga jenis pemilih:

Selector Makna Example
MinimizeButton AutomationId (ditampilkan saat unik — stabil, lebih disukai) winapp ui invoke MinimizeButton -a myapp
btn-close-d1a0 Simpul semantik (ditampilkan ketika tidak ada AutomationId yang unik) winapp ui invoke btn-close-d1a0 -a myapp
Submit Pencarian teks biasa terhadap Name/AutomationId (substring tidak peka huruf besar/kecil) winapp ui invoke Submit -a myapp

Pemilih AutomationId adalah pengidentifikasi set pengembang (AutomationProperties.AutomationId di XAML). Ketika AutomationId unik di seluruh pohon UI, inspect dan search memperlihatkannya langsung sebagai pemilih - ini bertahan dari perubahan tata letak, pelokalan, dan restrukturisasi pohon.

Pemilih simpul (misalnya, btn-close-d1a0) dihasilkan ketika tidak ada AutomationId unik. Format: prefix-name-hash. Hash memvalidasi identitas elemen tetapi mungkin kedaluarsa setelah UI berubah.

Memeriksa format output

inspect Perintah menunjukkan pohon elemen dengan output berwarna (pemilih dalam sian, nama berwarna hijau, metadata berwarna abu-abu):

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

Kata pertama pada setiap baris adalah pemilih — gunakan dengan perintah lainui. Ketika elemen memiliki AutomationId yang unik, elemen tersebut digunakan secara langsung (misalnya, TabView, NewTabButton). Ketika tidak ada AutomationId unik, simpul yang dihasilkan digunakan (misalnya, tab-newtab-5f5b).

Simpul semantik

Simpul menggunakan format : prefix-normalizedname-hash di mana:

  • awalan — singkatan jenis 3 huruf (btn, txt, chk, cmb, itm, tab, img, lbl, pn, win, grp, lnk, mnu, dll.)
  • normalizedname — huruf kecil alfanumerik dari AutomationId (lebih disukai) atau Nama, maks 15 karakter
  • hash — hash 4-char hex dari RuntimeId elemen (memvalidasi identitas elemen)

Simpul aman shell (tanpa karakter khusus), unik, dan dapat digunakan langsung sebagai argumen. Hash memberikan deteksi kedaluarsa — jika elemen telah diganti, Anda mendapatkan: "Elemen mungkin telah berubah. Jalankan kembali inspeksi."

Elemen tanpa nama atau AutomationId hanya menunjukkan awalan + hash (misalnya, pn-c8a3).

Mendisambiguasi beberapa kecocokan

Simpul dari inspect/search output bersifat unik, tetapi dapat berubah di seluruh perubahan tata letak - gunakan melalui nama atau teks jenis biasa saat beberapa kecocokan. Ketika pemilih ambigu, CLI mencetak semua kecocokan dengan simpulnya sehingga Anda dapat memilih yang tepat dan menjalankan kembali dengan simpul tersebut.

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

Gunakan teks biasa untuk mencari elemen — tidak diperlukan sintaksis khusus:

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

Saat pencarian teks cocok dengan beberapa elemen (misalnya, PengaturanExpander di mana Grup, Tombol, dan Teks semuanya memiliki nama yang sama), CLI secara otomatis memilih satu-satunya elemen yang dapat dipanggil. Jika beberapa dapat dipanggil, ia mencantumkan semua kecocokan dengan simpul.

Untuk hasil pencarian yang tidak dapat dipanggil (misalnya, TextBlock di dalam Tombol), pencarian secara otomatis menampilkan leluhur terdekat yang dapat dipanggil — elemen induk yang dapat Anda gunakan dengan invoke. Ini berfungsi untuk semua pemilih pencarian:

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

Pemilih yang muncul dapat digunakan secara langsung:

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

Commands

status

Sambungkan ke aplikasi dan tampilkan info koneksi.

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

Memeriksa

Lihat pohon elemen UI. Output menunjukkan simpul semantik dengan indentasi 2 spasi untuk hierarki:

winapp ui inspect -a notepad                    # full window tree, depth 3
winapp ui inspect -a notepad --depth 5          # deeper tree
winapp ui inspect txt-searchbox-e5f6 -a notepad # subtree rooted at element
winapp ui inspect --ancestors btn-close-d1a2 -a notepad  # walk up from element to root
winapp ui inspect -a myapp --interactive        # 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

Contoh output (default):

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)

Contoh output (--interactive — hanya elemen yang dapat dipanggil, daftar datar):

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)

Elemen dapat menunjukkan penanda status ini:

  • [on] / [off] / [indeterminate] — status toggle/checkbox
  • [collapsed] / [expanded] — perluas/ciutkan status untuk pohon, kotak kombo, item menu
  • [scroll:v] / [scroll:h] / [scroll:vh] — kontainer yang dapat digulir (vertikal, horizontal, atau keduanya)
  • [offscreen] — elemen tidak terlihat di layar
  • [disabled] — elemen tidak diaktifkan
  • value="..." — konten teks saat ini untuk elemen yang dapat diedit (jika berbeda dari Nama)

Temukan elemen yang cocok dengan pemilih. Output menunjukkan simpul semantik:

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

Contoh output:

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

Simpul yang ditampilkan dalam output (misalnya, btn-minimize-d1a0) dapat digunakan langsung dengan perintah lain:

winapp ui invoke btn-minimize-d1a0 -a notepad

get-property

Membaca nilai properti dari elemen. Termasuk status khusus pola (ToggleState, Value, IsSelected, dll.).

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

cuplikan layar

Ambil jendela atau elemen sebagai PNG. Ketika ada beberapa jendela (misalnya, dialog aplikasi + terbuka), jendela tersebut terdiri dari satu PNG dengan setiap jendela dijahit.

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)

Saat dialog atau popup terbuka, semua jendela terdiri dari satu PNG sehingga Anda dapat melihat status antarmuka pengguna lengkap dalam satu gambar.

Jalur pengambilan default menggunakan Windows. Graphics.Capture (WGC), membaca permukaan Aktual yang terdiri dari DWM — mempertahankan sudut bulat, transparansi, dan bekerja bahkan saat jendela dihilangkan oleh windows lainnya. Jika WGC tidak tersedia (build Windows yang lebih lama) CLI akan kembali ke PrintWindow.

Gunakan --capture-screen saat Anda perlu mengambil menu popup, dropdown, flyout, atau overlay tipsalat yang tidak dimiliki oleh jendela target. --capture-screen membaca dari layar DC dan membawa jendela ke latar depan terlebih dahulu. Gunakan --focus jika Anda hanya ingin memajukan jendela tanpa beralih mode pengambilan (misalnya, untuk memastikan cuplikan layar cocok dengan apa yang saat ini dilihat pengguna).

rekaman

Rekam jendela atau wilayah elemen ke H.264 MP4. Secara default, perekaman berlanjut hingga Ctrl+C atau, untuk stdin yang dialihkan, baris baru atau EOF.

# 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

Opsi:

  • --duration-sec N — Rekam selama N detik. Default 0 rekaman hingga dihentikan.
  • --fps N — Bingkai target per detik (default 15).
  • --max-edge N — Downscale sehingga tepi terpanjang paling banyak N piksel (0 = tanpa downscale).
  • --capture-screen — Ambil dari layar DC (termasuk overlay/popup; latar depan jendela).
  • --output <path> — Jalur MP4 output. Secara default menjadi recording-<timestamp>-<guid>.mp4.
  • --frames — Tulis bukti JPEG bertanda waktu ke <output-name>.frames. Mendukung 1-30 fps dan --max-edge 64-4096 (default 1280). Data bingkai dibatasi pada 1 GiB; MP4 berlanjut jika batas tercapai.

Artefak bingkai yang dapat dibaca agen:

demo.mp4
demo.frames/
  manifest.json
  frames.ndjson
  frames/
    frame-000000-t000000000012.jpg

frames.ndjson memiliki satu baris per sampel dengan sampleIndex, monotonik elapsedMs, MP4-relatif mediaTimeMs, imageIndex, file, dan changed. Sampel identik piksel berturut-turut menggunakan kembali JPEG kualitas-85 sebelumnya.

manifest.json merekam permintaan, waktu, status MP4, dimensi gambar, dan status (complete, partial, atau truncated). Waktu terpotong mencakup awalan yang dipertahankan, sementara video menjelaskan MP4 lengkap.

Dengan --frames, jalur MP4 dan bingkai yang ada tidak diganti. Jika finalisasi MP4 gagal, bingkai yang dipertahankan diterbitkan di bawah <output-name>.frames.partial-*. Artefak bingkai berisi konten layar yang tidak terenkripsi; menanganinya seperti cuplikan layar atau video.

Mode pengambilan (dilaporkan di bidang JSON mode ):

  • wgc— Windows Graphics Capture (default; berfungsi saat jendela dikoreksi).
  • printwindow — GDI PrintWindow (fallback ketika WGC tidak tersedia pada sistem/sesi ini; jalankan kembali dengan --capture-screen untuk menggunakan DC layar sebagai gantinya).
  • screen — Layar DC melalui --capture-screen (termasuk overlay/popup; membawa jendela ke latar depan).

Output JSON (--json):

  • stdout: Hasil rekaman akhir, termasuk irama, alasan berhenti, opsional frameArtifacts, dan peringatan.
  • stderr: Satu objek JSON per baris: recording-started peristiwa setelah bingkai pertama, diikuti oleh kesalahan jika perekaman nanti gagal. Jalur bingkai hanya disertakan ketika output bingkai aktif.

Kode kesalahan:

  • element_not_found — Pemilih tidak cocok.
  • ambiguous_selector — Pemilih cocok dengan beberapa elemen; gunakan simpul yang disarankan.
  • invalid_arguments — Nilai opsi tidak valid.
  • output_exists — Dengan --frames, direktori MP4 atau bingkai sudah ada.
  • frame_output_failed — Artefak tidak dapat dipertahankan setelah output bingkai gagal.
  • partial_output — Hanya satu artefak yang selesai; inspeksi partialOutput dan recoveryHint.

Batasan yang diketahui: Merekam elemen di dalam popup berjendela dapat menangkap jendela yang mendasar. Rekam seluruh jendela atau gunakan ui screenshot --capture-screen. Lihat #646.

Aktifkan elemen secara terprogram (klik tombol, alihkan kotak centang, perluas kotak kombo).

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

Pola percobaan secara berurutan: InvokePattern → TogglePattern → SelectionItemPattern → ExpandCollapsePattern.

klik

Klik elemen di koordinat layarnya menggunakan simulasi mouse. Gunakan ini untuk kontrol yang tidak mendukung InvokePattern (misalnya, header kolom, item daftar).

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

Seperti kata kerja input-menyuntikkan lainnya, click membawa target ke latar depan dan gagal dengan cepat (no_interactive_desktop pada desktop terkunci/aman, foreground_not_target jika fokus tidak dapat ditransfer) daripada mengklik jendela yang salah. Ini juga menyelesaikan kembali elemen tepat sebelum tombol-turun: setelah memosisikan kursor, itu melakukan satu pemeriksaan posisi akhir, sehingga target yang terus bergerak/animasi gagal dengan target_moved alih-alih melaporkan keberhasilan setelah klik mendarat di ruang kosong - keberhasilan yang dilaporkan berarti target masih ada ketika tombol turun.

seret

Tekan tombol mouse pada satu titik, pindahkan ke titik lain, lalu lepaskan dengan drag <from> <to>, di mana setiap titik akhir adalah pemilih elemen (menyeret dari/ke tengah elemen) atau koordinat x,ylayar persis seperti yang dilaporkan oleh winapp ui inspect. Campur dan cocokkan dengan bebas (pemilih→selektor, pemilih→koord, koord→koord).

SendInput Menggunakan dengan perpindahan menengah sehingga aplikasi melihat aliran WM_MOUSEMOVE pesan yang realistis. Gunakan untuk menyusun ulang/mengubah ukuran handel, penggeser, menggambar kanvas, dan seret dan letakkan.

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

Opsi:

  • --right — Seret dengan tombol kanan mouse alih-alih tombol kiri.
  • --hold-ms <ms> — Tahan tombol di awal sebelum bergerak (default: 0). Dengan <from> == <to> (tidak ada gerakan) ini melakukan gerakan tekan-dan-tahan/ tekan panjang .
  • --dwell-ms <ms> — Tinggal di tujuan setelah pindah, sebelum merilis (default: 0). Mari kita hilangkan target/ gabungkan overlay yang lengan dari hover berkelanjutan (daripada saat kursor tiba) kait sebelum tombol-up.

Bare x,y adalah koordinat layar dalam laporan ruang winapp ui inspect/search yang sama, dan pemilih menyelesaikan ke pusat elemen — periksa terlebih dahulu untuk memilih titik.

Seperti send-keys --via send-input, drag menyuntikkan koordinat di seluruh OS di layar setelah membawa target ke latar depan. Jika fokus tidak dapat dibawa ke target (misalnya pencegahan pencurian fokus dari proses latar belakang), perintah gagal (foreground_not_target) daripada menyeret di jendela yang salah — fokus atau klik jendela terlebih dahulu. Pada desktop terkunci/aman, desktop gagal dengan no_interactive_desktop. Setiap titik akhir elemen diselesaikan kembali segera sebelum seret; jika masih bergerak/mengubah ukuran (target animasi), perintah gagal dengan target_moved alih-alih menyeret ke titik kedaluarsa. (Titik akhir bare x,y tidak dapat diverifikasi ulang, sehingga digunakan as-is.)

Sentuh

Suntikkan gerakan sentuh sintetis menggunakan API Windows pointer-injection. Jangkar kontak adalah pemilih elemen (menggunakan pusat elemen) atau koordinat x,ylayar eksplisit melalui --at (laporan ruang winapp ui inspect yang sama). Gunakan untuk mengetuk/menekan interaksi dan gerakan multi-sentuh yang tidak dapat diekspresikan oleh simulasi mouse.

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)

Opsi:

  • --gesture <g>tap (default), double-tap, , long-pressswipe, pinch, stretch.
  • --at <x,y> — Titik awal eksplisit (koordinat layar). Default ke pusat elemen pemilih.
  • --to-point <x,y> — Titik akhir untuk swipe. Lebih diutamakan daripada --direction.
  • --direction <right|left|up|down> — Arah gesek (default: right). Dikombinasikan dengan --distance untuk menghitung titik akhir ketika --to-point tidak diberikan.
  • --distance <px> — Penyebaran jari untuk pinch/stretch, atau gesek jarak dalam piksel.
  • --hold-ms <ms> — Tahan kontak sebelum mengangkat (waktu penahanan tekan lama; default ke 500 ms saat long-press tidak diatur).
  • --duration-ms <ms> — Meluncurkan waktu untuk gerakan bergerak (gesek/jepit/regangkan; default 300).
  • --fingers <n> — Jumlah kontak (1–10; default 1). pinch / stretch selalu gunakan 2.

Keamanan injeksi. touch menolak untuk menyuntikkan kecuali handel jendela target bukan nol diselesaikan dan jendela tersebut menahan latar depan — gagal ketika no_target tidak ada jendela yang dapat diselesaikan, foreground_not_target jika fokus tidak dapat ditransfer, atau no_interactive_desktop pada desktop terkunci/aman. Setiap koordinat (pusat elemen, eksplisit--at/--to-point, dan titik arah yang dihasilkan) diperiksa terhadap persegi panjang jendela target; titik di luar jendela muncul sebagai peringatan non-fatal (warnings[]entri dalam , atau baris peringatan dalam --jsonmode teks) dan injeksi masih berlanjut - mencocokkan kata kerja mouse (click/drag/hover/scroll), yang juga menyuntikkan koordinat di luar jendela. --fingers di atas 10 ditolak di muka.

Catatan perangkat keras. Sentuh lebih suka perangkat penunjuk sintetis modern (CreateSyntheticPointerDevice(PT_TOUCH)) dan kembali ke API warisanInitializeTouchInjection/InjectTouchInput. Jika injeksi tidak didukung pada perangkat/sesi saat ini, perintah menampilkan kode kesalahan Win32 yang sebenarnya (misalnya "tidak didukung") daripada melaporkan keberhasilan palsu — perlakukan pintu keluar bukan nol sebagai "sentuhan tidak terkirim".

sesi Desktop Jauh /VM. Dalam Desktop Jauh (RDP) atau beberapa sesi VM, OS dapat menerima sentuhan sintetis (keluar 0) tanpa benar-benar mencapai aplikasi target. Saat sesi jarak jauh terdeteksi, touch menambahkan peringatan ketidakpastian pengirimanwarnings[] entri di --json, atau baris peringatan dalam mode teks. ✅Sebuah /exit 0 kemudian berarti panggilan injeksi berhasil, bukan berarti aplikasi menerima input; mengonfirmasi efeknya dengan ui screenshot/ui inspect kapan itu penting.

pena

Masukkan input pena/stylus sintetis — ketukan dan goresan tinta — menggunakan API penunjuk sintetis Windows (CreateSyntheticPointerDevice(PT_PEN); Windows 10 1809+). Targetkan pusat elemen, titik eksplisit --at , atau goresan tinta penuh --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

Opsi:

  • --at <x,y> — Titik kontak pena (koordinat layar). Default ke pusat elemen pemilih. Diabaikan ketika --path diberikan.
  • --path "<x,y x,y …>" — Jalur goresan tinta sebagai pasangan yang dipisahkan x,y spasi putih (jalur satu titik adalah ketukan).
  • --pressure <0.0–1.0> — Tekanan pena (default 0,5).
  • --tilt-x <deg> / --tilt-y <deg> — Sudut miring pena, −90 hingga 90 (default 0).
  • --eraser — Gunakan ujung penghapus pena alih-alih tip.
  • --duration-ms <ms> — Total waktu perjalanan goresan dalam milidetik yang didistribusikan sebagai bingkai PEMBARUAN terinterpolasi di seluruh jalur (default: ~10 ms per titik arah). Gunakan ini untuk mengontrol seberapa cepat pena bergerak dari awal hingga akhir.

Keamanan injeksi. Seperti touch, pen menolak untuk menyuntikkan tanpa jendela target non-nol, latar depan (no_target / foreground_not_target / no_interactive_desktop) dan memeriksa setiap titik tinta terhadap persegi panjang jendela target, memunculkan koordinat di luar jendela sebagai peringatan non-fatal (warnings[] dalam --json, atau garis peringatan dalam mode teks) saat masih menyuntikkan — konsisten dengan kata kerja mouse. Tidak valid --pressure (di luar 0,0–1,0) atau kempis (di luar ±90°) ditolak di depan.

sesi Desktop Jauh /VM. Perutean pena sangat tidak dapat diandalkan melalui Desktop Jauh: panggilan injeksi dapat melaporkan keberhasilan (keluar 0) sementara tidak ada input pena yang mencapai aplikasi. Ketika sesi jarak jauh terdeteksi, pen menambahkan peringatan ketidakpastian pengiriman (warnings[] dalam --json, atau baris peringatan dalam mode teks) sehingga tidak salah untuk pengiriman yang ✅ dikonfirmasi. Validasi alur dependen pena pada desktop interaktif lokal.

Hover

Pindahkan mouse ke tengah elemen untuk memicu efek hover (tipsalat, flyout, status visual). SendInput Menggunakan untuk gerakan mouse realistis dengan wiggle kecil, lalu menunggu waktu tinggal yang dapat dikonfigurasi.

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

Opsi:

  • --dwell-time <ms> — Waktu dalam milidetik untuk menunggu setelah melayang agar efek muncul (default: 800, rentang: 0–10000)

send-keys

Kirim input keyboard sintetis — rekan keyboard ke click. UIA tidak memiliki pola injeksi keyboard, jadi ini turun ke lapisan Win32. Gunakan untuk navigasi keyboard (panah, Tab, Enter, Esc), pintasan (ctrl+c, alt+f4), dan mengetik ke dalam kontrol yang memerlukan peristiwa per tombol daripada set-value's atomic write.

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

Tata bahasa kunci (token yang dipisahkan spasi putih, string multi-token kutip):

  • Kunci bernamaenter/return, , tabesc/escape, space, backspace, , delete/delinsert, home, end,pageup/pgup , , pagedown/pgdn, up/down/left/right, f1f16, apps, printscreen, . capslock
  • Urutan — beberapa token ditekan secara berurutan: down down enter.
  • Kombo pengubahctrl, shift, alt, win digabungkan dengan +: ctrl+shift+t, alt+f4.
  • Teks literal — token apa pun yang bukan kunci yang diketahui diketik karakter berdasarkan karakter: hello. Kata harfiah yang berdekatan menyimpan ruang di antara mereka, sehingga frasa yang dikutip seperti "Hello world" diketik verbatim (ruang dipertahankan); harfiah yang hanya berisi + seperti C++ atau a+b diketik sebagai teks, tidak diurai sebagai kombo.
  • Escape harfiah eksplisit — awali token dengan text= untuk mengetikkannya verbatim bahkan ketika bertabrakan dengan nama kunci atau pengubah: text=enter ketik kata "enter" alih-alih menekan Enter, dan text=ctrl+a ketik string harfiah. Mencerminkan vk= escape; nilai escape masih bersatu dengan kata-kata harfiah yang berdekatan (text=down low → "turun rendah"). Karena token adalah whitespace-split (dan literal yang berdekatan bergabung kembali dengan satu spasi), gunakan escape garis miring terbalik di dalam text= nilai untuk mengetik spasi kosong yang tidak akan bertahan: \s → spasi, \t tab →, \n → garis baru, \r → garis miring baru, \\ → garis miring terbalik harfiah. \n, \r, dan \r\n masing-masing menyisipkan hentian baris tunggal (Enter / VK_RETURN), jadi text=line1\nline2 dan text=line1\r\nline2 keduanya ketik satu baris baru. Jadi text=a\s\sb , ketik "a b" (spasi ganda), dan text=\shi mempertahankan ruang di depan. Escape yang tidak dikenal (misalnya \x) adalah verbatim kiri.
  • Literal seluruh argumen (--verbatim) — ketika seluruh payload adalah teks literal, teruskan --verbatim alih-alih melarikan diri setiap token dengan text=. Ini mengetik seluruh argumen kunci persis seperti yang diberikan — tidak ada interpretasi named-key/combo/vk=/text=— dan, tidak seperti jalur normal, mempertahankan spasi kosong internal yang tepat (tidak ada penciutan) tanpa memerlukan .\s Jadi send-keys "down down enter" --verbatim ketik kata-kata, dan send-keys "a b" --verbatim menyimpan spasi ganda. Escape garis miring terbalik tidak didekodekan dalam --verbatim mode ( \s diketik sebagai garis miring terbalik dan "s"); gunakan text= token saat Anda memerlukan karakter kontrol yang lolos.
  • Kunci virtual mentahvk=0xNN (hex) atau vk=NN (desimal) untuk kunci tanpa nama yang mudah diingat.

Opsi:

  • --target <selector> — Fokuskan elemen ini (melalui UIA) sebelum mengirim kunci. Tanpa itu, kunci masuk ke elemen aplikasi yang saat ini berfokus.
  • --verbatim — Ketik seluruh argumen kunci sebagai teks harfiah (tanpa kunci/kombo/vk=/text= penguraian) dan pertahankan spasi kosong yang tepat. Bentuk seluruh argumen dari escape per token text= .
  • --via <transport>post-message (default) mempostingWM_KEYDOWN/WM_KEYUP/WM_CHARke antrean jendela target. Ini adalah UIPI yang ditargetkan HWND dan melewati (bekerja di seluruh tingkat integritas). send-input menyuntikkan os-wide melalui SendInput dan pergi ke jendela latar depan.

Memilih batas transportasi/yang diketahui:

  • post-message adalah default karena melewati UIPI dan tidak bergantung pada jendela latar depan. Batas: ini tidak dapat memicu hotkey global yang terdaftar melalui WH_KEYBOARD_LL kait tingkat rendah (input ketukan upstream dari antrean jendela apa pun), dan aplikasi yang membaca status kunci mentah melalui GetAsyncKeyState mungkin tidak mengamati pengubah yang dipegang. Ini secara otomatis menyelesaikan dan memposting ke jendela anak yang berfokus pada utas target (melalui GetGUIThreadInfo) setelah latar depan, sehingga aplikasi Win32/WinForms klasik yang kontrolnya adalah kunci penerima jendela anak terpisah tanpa menargetkan kontrol secara manual. Aplikasi WinUI 3 / UWP memiliki kontrol XAML tanpa jendela tanpa HWND anak, sehingga yang diposting WM_CHAR/WM_KEYDOWN tidak memiliki apa pun untuk mendarat dan dihilangkan - pasca-pesan tidak dapat mendorongnya (perintah memperingatkan dan keluar 0); gunakan .--via send-input (WPF jendela adalah HWND tunggal dan kunci rute ke elemen yang berfokus pada internal, sehingga pasca-pesan berfungsi di sana.)
  • send-inputmenghasilkan input yang sepenuhnya nyata (pengubah yang terlihat GetAsyncKeyStateoleh , menembakkan kait tingkat rendah) tetapi pergi ke jendela apa pun yang latar depan dan diblokir oleh UIPI saat menyuntikkan dari proses yang ditinggikan ke target integritas yang lebih rendah (AppContainer/AppX). Jika send-input melaporkan kegagalan, target kemungkinan ditinggikan atau aplikasi AppX — gunakan post-message, atau jalankan CLI pada tingkat integritas yang cocok. Sebagai penjaga keamanan, send-input memverifikasi jendela target sebenarnya berada di latar depan segera sebelum menyuntikkan dan gagal (foreground_not_target) daripada mengetik ke jendela yang salah jika fokus tidak dapat dibawa ke jendela tersebut — fokus atau klik jendela terlebih dahulu. Pada desktop terkunci atau aman gagal dengan no_interactive_desktop (tidak ada jendela latar depan yang disuntikkan) — buka kunci sesi, atau gunakan kata kerja pola UIA (set-value, invoke).
  • Combo yang dicadangkan sistem (win+l, , win+r, ctrl+shift+escctrl+alt+del, alt+tab, alt+f4, ctrl+esclone win/printscreen, ...) bertindak pada OS/shell daripada hanya target saat dikirim di seluruh OS. send-input menolaknya secara default (kesalahan dengan invalid_arguments dan tidak mengirim apa-apa) karena menyuntikkannya di tingkat OS memiliki efek jauh di luar jendela target (misalnya win+l akan mengunci sesi). Teruskan --allow-system-keys untuk ikut serta - ini memungkinkan Anda mendorong hotkey global seperti PowerToys' win+shift+v atau win+r (kait tingkat rendah global menonton aliran input di seluruh OS, sehingga kombo yang disuntikkan menembakkannya). Pengecualian yang tetap diblokir bahkan dengan --allow-system-keys:win+l mengunci stasiun kerja yang LockWorkStation() tidak dapat dipulihkan dari otomatisasi (memutus sesi CI dan desktop jarak jauh), dan ctrl+alt+del merupakan Secure Attention Sequence (SAS) yang Windows turun dari input yang disuntikkan terlepas dari bendera — tidak pernah dapat berlaku, sehingga kesalahan (invalid_arguments, keluar 1) alih-alih melaporkan keberhasilan yang menyesatkan. Kombo lain (alt+f4, ctrl+shift+esc, , win+r...) diizinkan dengan bendera — pemanggil berhati-hatilah. Atau, untuk mengirimkan kombo sistem ke penggunaan --via post-messagejendela tertentu , yang tercakup dalam jendela dan tidak terpengaruh (yang diposting win+l tidak berbahaya, meskipun yang diposting alt+f4 masih menutup jendela target).

Peristiwa per-keystroke (KeyDown / TextChanged):

  • Kunci bernama dan kombo pengubah (down, enter, ctrl+shift+t, vk=0xNN) menembakkan nyata KeyDown (dan KeyUp) pada kedua transportasi — mereka dikirimkan sebagai peristiwa diskrit WM_KEYDOWN/WM_KEYUP (atau SendInput kunci virtual).
  • Teks yang dititik harfiah (hello) berbeda menurut transportasi:
    • --via send-input memetakan setiap karakter ke tombol virtualnya (plus Shift) pada tata letak keyboard aktif, sehingga target melihat karakter asli KeyDown dengan tombol virtual yang benar diikuti oleh yang disusun OS (menaikkan WM_CHARTextChanged) — yaitu satu penekanan tombol penuh per karakter. Karakter tidak dapat dijangkau pada tata letak saat ini (atau membutuhkan Ctrl/AltGr) kembali ke paket Unicode sehingga karakter yang tepat masih mendarat. Gunakan send-input saat Anda membutuhkan keakuratan per-keystroke KeyDown (misalnya mengendarai WinUI 3 / WPF TextBox yang kunci handler-nya mati KeyDown). Untuk host uji WinUI 3 normal (non-elevated), bawa jendelanya ke latar depan terlebih dahulu (winapp ui focus / klik) karena send-input menargetkan jendela latar depan.
    • --via post-message memposting satu WM_CHAR per karakter ( tidak memposting WM_KEYDOWN/WM_KEYUP untuk teks yang diekstrak — yang dicadangkan untuk kunci/kombo bernama), yang tidak menaikkan per karakter KeyDown. Ini secara otomatis ditargetkan ulang ke kontrol anak yang berfokus pada jendela, sehingga kontrol edit klasik Win32/WinForms WM_CHAR-driven mendaratkan teks (menaikkan TextChanged). Peringatan: Aplikasi WinUI 3 / UWP / XAML (target utama winapp) memiliki kontrol tanpa jendela yang diabaikan diposting WM_CHAR/WM_KEYDOWN — jadi teks harfiah atau kunci bernama (Enter, digit, ...) mencapainya, meskipun perintah melaporkan keberhasilan. Ini memancarkan peringatan ketika target terlihat seperti XAML dan masih keluar 0 (PostMessage adalah fire-and-forget dan tidak dapat mengonfirmasi pengiriman). Gunakan --via send-input untuk mendorong aplikasi WinUI 3 / UWP / WPF; cadangan post-message untuk kontrol Win32 klasik atau ketika Anda hanya membutuhkannya dalam cakupan jendela di seluruh tingkat integritas.

Output JSON (--json): hasilnya hwnd adalah jendela efektif tempat kunci dikirimkan — untuk --via post-message ini adalah kontrol anak terfokus yang diselesaikan ketika perintah ditargetkan ulang (belum tentu jendela tingkat -w/-a/-e atas), sehingga otomatisasi dapat mengonfirmasi dengan tepat di mana input mendarat. Ketika target efektif itu terlihat seperti host XAML tanpa jendela, peringatan pengiriman di atas juga muncul sebagai warnings[] entri (saran yang sama yang ditampilkan pada konsol), sehingga ✅ keluar 0 tidak keliru untuk pengiriman yang dikonfirmasi.

set-value

Tetapkan nilai pada elemen yang dapat diedit secara terprogram (tanpa penekanan tombol, tanpa latar depan aplikasi). Menggunakan rantai fallback:

  1. ValuePattern — TextBox, ComboBox, PasswordBox, dan kontrol yang paling dapat diedit.
  2. RangeValuePattern — kontrol numerik (Slider, ProgressBar) saat nilai diurai sebagai angka.
  3. LegacyIAccessible (IAccessible::put_accValue) — fallback untuk kontrol edit khusus TextPattern yang tidak mengekspos ValuePattern (misalnya kotak rich-edit / Document compose). Ini menutup celah baca/tulis di mana get-value bisa membaca kontrol seperti itu tetapi set-value tidak bisa.
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

Jika tidak ada dari tiga pola yang dapat mengatur nilai, set-value gagal dengan kesalahan yang jelas yang menunjuk send-keys sebagai upaya terakhir.

Tidak setiap editor kaya mendukung set terprogram. Fallback LegacyIAccessible hanya berfungsi pada kontrol yang aksesibilitasnya mengimplementasikan IAccessible::put_accValue — kontrol edit kaya Win32 asli dan permukaan kompos Chromium/Electron/WebView2 biasanya dilakukan. WinUI 3 RichEditBox dan WPF RichTextBox tidak mendukung pengaturan nilai terprogram — secara desain mereka mengekspos konten mereka ke UI Automation sebagai baca-saja (Pola teks, tidak ada pola Nilai yang dapat diatur), sehingga set-value tidak dapat menulis kepada mereka. Gunakan send-keys (yang membutuhkan desktop latar depan yang tidak terkunci) untuk desktop tersebut.

get-value

Baca nilai saat ini dari elemen. Menggunakan rantai fallback cerdas: TextPattern (RichEditBox, Document) → ValuePattern (TextBox, Slider) → SelectionPattern (ComboBox, RadioButton, TabView) → Name (label).

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

Pindahkan fokus keyboard ke elemen.

winapp ui focus txt-textbox-a4b1 -a notepad

scroll-into-view

Gulir elemen ke area yang terlihat.

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

tunggu-untuk

Tunggu hingga elemen muncul, menghilang, atau memiliki nilai mencapai target.

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

Gulir

Gulir elemen kontainer. Temukan kontainer yang dapat digulir dengan search scroll — cari [scroll:v] penanda (vertikal) atau [scroll:h] (horizontal).

# 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

Opsi:

  • --direction <up|down|left|right> — Gulir secara bertahap melalui ScrollPattern.
  • --to <top|bottom> — Lompat ke awal/akhir melalui ScrollPattern.
  • --wheel <notches> — Mensintesis input roda mouse di atas tengah elemen melalui SendInput, dalam takik roda (penahanan): 1 = satu takik naik/menjauh, -1 = satu takik ke bawah/ke arah, 3 = tiga takik ke atas. (Setiap notch adalah Windows WHEEL_DELTA 120 unit yang SendInput mengonsumsi; CLI menskalakan takik sebesar 120 untuk Anda.) Melewati ScrollPattern.

--direction, --to, dan --wheel saling eksklusif — berikan tepat satu. Karena --wheel menyuntikkan input di seluruh OS pada koordinat layar, itu membawa target ke latar depan terlebih dahulu dan gagal (foreground_not_target) jika fokus tidak dapat ditransfer, daripada menggulir jendela yang salah.

get-focused

Perlihatkan elemen yang saat ini memiliki fokus keyboard.

winapp ui get-focused -a myapp

list-windows

Mencantumkan semua jendela yang terlihat untuk aplikasi, termasuk popup dan dialog. Secara default, jendela tanpa judul dengan ukuran nol (jendela sistem yang tidak terlihat) dikecualikan.

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

Dukungan Kerangka Kerja

Kerangka kerja Memeriksa cari Memohon set-value cuplikan layar
WPF ✅ Pohon penuh ✅ Semua properti ✅ Semua pola ✅ ¹
WinForms
Win32
WinUI 3 ✅ ¹
Elektron ⚠️ Pohon kromium ⚠️ Terbatas ⚠️ Bervariasi ⚠️ Bervariasi
Flutter ⚠️ Dasar ⚠️ Dasar ❌ Minimal

¹ set-value berfungsi pada kontrol apa pun yang mengekspos ValuePattern/RangeValuePattern, ditambah kontrol edit khusus TextPattern yang aksesibilitasnya mengimplementasikan IAccessible::put_accValue (fallback LegacyIAccessible). WinUI 3 RichEditBox dan WPF RichTextBox adalah pengecualian — hanya mengekspos pola Teks baca-saja (tidak ada pola Nilai yang dapat diatur), sehingga tidak dapat diatur secara terprogram berdasarkan desain; gunakan send-keys (desktop interaktif diperlukan) untuk mengetiknya.

Troubleshooting

Kesalahan Cause Solution
"Tidak ada aplikasi yang berjalan yang ditemukan" Aplikasi tidak berjalan atau nama tidak cocok Periksa nama proses atau gunakan PID
"Beberapa jendela cocok" Nilai ambigu -a Gunakan -w <HWND> dari opsi yang tercantum
"memiliki beberapa jendela" Proses memiliki beberapa jendela Gunakan -w <HWND> untuk menargetkan yang spesifik
"Pemilih cocok dengan elemen N" Pemilih warisan ambigu Gunakan simpul dari inspect output, atau tambahkan [0], [1] ke pemilih warisan
"Elemen mungkin telah berubah" Hash simpul tidak cocok dengan elemen saat ini Jalankan inspect kembali atau search untuk mendapatkan simpul segar
"tidak mendukung pola pemanggilan apa pun" Elemen tidak dapat dipanggil Gunakan inspect pada elemen untuk menemukan anak yang dapat dipanggil
"Tidak ada jendela UIA yang ditemukan" UIA tidak dapat melihat prosesnya Gunakan list-windows untuk menemukan HWND, lalu -w
"Jendela memiliki ukuran nol" Jendela diminimalkan Aplikasi akan dipulihkan secara otomatis
Popup/dropdown tidak ada di cuplikan layar Pengambilan default adalah per jendela dan tidak menyertakan overlay yang tidak disetujui Gunakan --capture-screen bendera
element_not_found selama rekaman Pemilih diberikan tetapi tidak ada elemen yang cocok Jalankan inspect kembali atau search untuk mendapatkan pemilih baru
WGC tidak tersedia selama rekaman Init penangkapan WGC gagal; tidak ada fallback senyap Periksa GPU/driver; gunakan --capture-screen untuk menyetujui pengambilan screen-DC

Pola Umum

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

Menemukan teks dan memanggil induknya

# 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

Elemen duplikat disambiguate

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

Cuplikan layar dengan overlay 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

Menemukan, mengklik, dan memverifikasi

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

Interaksi dialog file

Dialog buka/simpan file adalah dialog Windows standar dengan dukungan UIA:

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

Gunakan inspect -w <dialog-hwnd> --interactive untuk menemukan siput aktual untuk dialog tertentu.

Mengapa ; untuk menautkan (bukan &&)

Operator PowerShell && dapat membeku saat CLI asli menulis ke stderr atau menggunakan urutan escape ANSI. Gunakan ; sebagai gantinya — menjalankan setiap perintah tanpa syarat dan menghindari kebuntuan ini. Ini juga lebih baik untuk alur kerja agen: Anda biasanya ingin cuplikan layar berjalan meskipun pemanggilan memiliki pintu keluar bukan nol.

Pola Pengujian CI

Gunakan perintah winapp ui dalam alur CI (GitHub Actions, Azure DevOps) untuk uji asap dan validasi UI. wait-for dengan --property dan --value bertindak sebagai pernyataan - mengembalikan kode keluar 1 pada waktu habis, gagal langkah CI secara otomatis.

Luncurkan dan uji di 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

Menegaskan status elemen dengan wait-for

wait-for --value polling hingga nilai elemen cocok dengan string yang diharapkan, menggunakan fallback cerdas yang sama dengan get-value (TextPattern → ValuePattern → SelectionPattern → Name). Mengembalikan kode keluar 0 pada kecocokan, keluar dari kode 1 pada waktu habis — menjadikannya pernyataan ramah CI. Gunakan --property untuk memeriksa properti UIA tertentu sebagai gantinya.

# 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

Menegaskan dengan output JSON

Gunakan --json dengan PowerShell atau jq untuk pernyataan yang lebih kompleks:

Kontrak kode keluar untuk search dan wait-for dalam mode: ketika tidak ada elemen yang cocok () atau waktu tunggu habis (), perintah menulis amplop hasil yang sepenuhnya dapat diurai --json ke search (wait-for atau ) dan mengembalikan { "matchCount": 0, ... }.{ "found": false, "timedOut": true, ... } Stderr kosong dalam --json mode (output pencatat ditekan). Cabang pada bidang amplop, atau pada $LASTEXITCODE, tergantung pada mana yang lebih ergonomi.

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

Contoh uji asap penuh

# 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