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, , search, get-propertyget-value, wait-for, set-value, invoke, scroll --direction/--to - mendorong aplikasi melalui pola UIA dan ramah tanpa kepala / sesi terkunci. screenshot adalah pengecualian di antara kata kerja yang tidak menyuntikkan: dibutuhkan giliran eksklusif dan penangkapannya dapat membutuhkan desktop interaktif yang dapat digunakan, karena mesin memulihkan target yang diminimalkan dan kembali ke latar depan ketika pengambilan bingkai tidak tersedia atau --capture-screen digunakan. 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

Menjalankan otomatisasi UI di Windows Sandbox

Untuk menjaga automasi tetap di luar desktop Anda, tambahkan --on sandbox ke perintah jalankan dan UI:

winapp run . --on sandbox --detach
winapp ui inspect --on sandbox -a MyApp
winapp ui invoke --on sandbox SubmitButton -a MyApp

--detach kembali setelah peluncuran; tanpanya, run menunggu aplikasi keluar. Terus --on sandbox pada setiap perintah tamu, termasuk yang menggunakan PID atau handel jendela. Lihat Windows eksekusi Sandbox untuk persyaratan klien, pengaturan singkat/sambungkan kembali perubahan fokus, koordinasi alur kerja, dan pengiriman output host.

Kueri terlingkup dan dititik

winapp ui search "Welcome to MyApp" -a myapp --root MailRow --type Text --class-name TextBlock
winapp ui get-value Subject -w 123456 --root MailRow --type TextBox
winapp ui get-property Subject -a myapp --root MailRow --type Edit --property Value
winapp ui wait-for Subject -a myapp --root MailRow --type Edit --value "Ready" --timeout 10000

search, , get-propertyget-value, dan wait-for terima filter opsional ini. Pemilih dan setiap filter yang disediakan harus cocok dengan elemen yang sama:

  • --root <selector> hanya mencari keturunan dari satu akar yang cocok secara unik, tidak pernah akar itu sendiri. Gunakan AutomationId atau slug dari inspect untuk memisahkan. Akar yang cocok dengan beberapa elemen gagal dengan ambiguous_selector, bahkan jika satu kecocokan dapat dipanggil. Akar yang hilang tidak menghasilkan kecocokan. Setelah akar ditemukan, kueri tidak mencari jendela popup yang tidak terkait, bahkan ketika tidak ada kecocokan turunan. Kueri tidak dibatasi oleh inspectkedalaman tampilan.
  • --type <control-type> cocok dengan jenis kontrol UIA, mengabaikan kasus. Satu-satunya alias adalah TextBox → Edit dan TextBlock → Text. Nama yang tidak diketahui (termasuk ID numerik dan ekspresi kartubebas) gagal dengan invalid_arguments.
  • --class-name <literal> cocok dengan seluruh UIA ClassNamepenyedia, mengabaikan kasus. Ini bukan substring, kartubebas, atau ekspresi reguler. Gunakan get-property --property ClassName untuk menemukan nilai penyedia; nama kelas tidak perlu sama dengan jenis kontrol UIA.

Kueri yang difilter menggunakan Tampilan Kontrol UIA, tampilan yang sama diperlihatkan oleh inspect. Node penyedia yang hanya diekspos dalam Tampilan Mentah tidak dikembalikan; gunakan inspect untuk menemukan kontrol yang berisi dan pemilihnya.

Semua 41 jenis resmi didukung: Button, CustomComboBoxCheckBoxHyperlinkEditImageListItemListMenuMenuBarCalendarTextTabItemTabStatusBarToolBarSpinnerSliderScrollBarToolTipRadioButtonProgressBarMenuItemTreeTreeItemSplitButtonDocumentWindowDataItemPaneDataGridHeaderHeaderItemThumbGroupTitleBarSeparatorTableSemanticZoom, . AppBar

wait-for menyelesaikan pemilih akar lagi pada setiap polling, sehingga akar mungkin muncul setelah perintah dimulai. Dengan --gone, akar absen berarti tidak ada keturunan yang cocok; akar ambigu adalah kesalahan, bukan keberhasilan. Pencarian yang terganggu bukan bukti hilangnya: jika elemen dihapus selama pencarian atau diganti sebelum --value dibaca, polling berikutnya memeriksa lagi; kesalahan pencarian atau baca lainnya gagal perintah. -w <HWND> membatasi penemuan akar ke pohon UIA jendela tersebut. Dengan -a, penemuan akar juga dapat menemukan jendela popup aplikasi. Kecocokan AutomationId akar yang tepat lebih diutamakan daripada kecocokan substring di semua jendela tersebut; beberapa kecocokan persis masih gagal dengan ambiguous_selector.

Simpul akar memilih elemen tersebut bahkan ketika jendela lain memiliki AutomationId yang sama. Jika akar yang dipilih diganti, simpul lamanya tidak lagi cocok; gunakan AutomationId atau akar nama saat Anda ingin polling mengikuti penggantian.

Saat filter ada, perintah yang membaca elemen tunggal gagal dengan ambiguous_selector jika lebih dari satu elemen tetap ada; persempit filter atau gunakan simpul unik. AutomationId yang tepat cocok mempertahankan prioritas daripada kecocokan substring, dalam cakupan yang difilter. Menghilangkan ketiga opsi mempertahankan perilaku kueri yang ada.

Mengoordinasikan alur kerja UI bersamaan

Windows hanya memiliki satu jendela latar depan, satu fokus keyboard, satu kursor, dan satu aliran input. Ketika dua winapp ui alur kerja berjalan pada desktop masuk yang sama sekaligus, mereka dapat mencuri fokus satu sama lain, menutup menu yang baru saja dibuka, atau memindahkan target keluar dari bawah klik tertunda.

Arbitrase selalu aktif. Setiap winapp ui perintah yang menyentuh desktop fisik bergantian, tanpa pengaturan dan tidak ada cara untuk mematikannya, sehingga dua agen tidak pernah dapat mengetik ke jendela satu sama lain. Perintah baca-saja terus berjalan secara bersamaan.

Kelangsungan antar perintah adalah keikutsertaan. Secara default setiap perintah adalah satu bidikan mandiri: perintah menunggu gilirannya, melakukan pekerjaannya, dan segera merilis desktop. Untuk mempertahankan desktop di beberapa perintah, berikan semua id alur kerja yang sama:

# Set once per logical UI workflow
$env:WINAPP_UI_WORKFLOW_ID = [guid]::NewGuid().ToString()

Yang perlu Anda ketahui:

  • Id alur kerja menamai satu alur kerja logis — belum tentu merupakan seluruh agen, dan belum tentu satu aplikasi. Gunakan nilai yang sama untuk bekerja sama dengan perintah (rekaman ditambah klik yang harus diambilnya); gunakan nilai yang berbeda untuk alur kerja independen, bahkan ketika satu agen meluncurkan keduanya.
  • Tanpa id, setiap perintah adalah satu bidikan independen. Ini masih arbitrase, tetapi tidak bank rahmat dan tangan desktop off saat selesai. Dua perintah no-id adalah alur kerja terpisah bahkan ketika diluncurkan dari shell yang sama.
  • Host fresh-shell dan adaptif harus menyuntikkan nilai yang sama. Jika setiap perintah berjalan di shell baru — yaitu cara kerja sebagian besar alat agen — satu-satunya hal yang dapat mengelompokkannya adalah eksplisit WINAPP_UI_WORKFLOW_ID yang diteruskan ke setiap panggilan yang bekerja sama.
  • Tenggang empat detik melindungi ledakan ketat, bukan penalaran model. Alur kerja dengan id menyimpan gilirannya selama perintah berikutnya dimulai dalam waktu empat detik. Itu mencakup perintah back-to-back dalam satu skrip; itu sengaja kedaluwarsa saat model sedang berpikir. Ini adalah fallback ketika Anda tidak dapat mengatakan Bahwa Anda selesai — ketika Anda bisa, jalankan winapp ui yield alih-alih menunggu.
  • Alur kerja adaptif harus membutuhkan kembali, memvalidasi ulang, dan memutar ulang. Setelah celah penalaran, alur kerja lain mungkin telah menggunakan desktop, jadi buka kembali menu, atasi kembali elemen, lalu bertindak. Kirim urutan end-to-end yang diketahui sebagai satu skrip ketat daripada menahan desktop saat Anda berpikir.
  • Pemesanan adalah afinitas pemilik terlebih dahulu, kemudian FIFO di antara yang lain. Meskipun alur kerja aktif atau di dalam rahmatnya, alur kerja mungkin tetap mengeluarkan perintah, bahkan jika alur kerja lain sudah menunggu. Setelah berjalan winapp ui yield atau tenggangnya kedaluwarsa, alur kerja tunggu disajikan dalam urutan kedatangan yang ketat. Oleh karena itu, aktivitas berkelanjutan menurut satu alur kerja dapat menunda orang lain tanpa batas waktu.
  • Tidak ada topi keras. Skrip panjang, rekaman yang tidak terbatas, atau perulangan kegagalan dapat memblokir alur kerja bermutasi lainnya.
  • Pembatalan atau penghentian proses adalah pemulihan untuk alur kerja langsung yang macet. Perintah menunggu mencetak status setelah satu detik dan dapat dihentikan dengan Ctrl+C, yang keluar 130.
  • Hanya biner yang diperbarui yang kompatibel yang bekerja sama. Build yang lebih winapp lama mendahului fitur ini dan tidak dikoordinasikan. Kode yang memanggil paket UI Automation NuGet secara langsung berada di luar jaminan ini sepenuhnya — koordinasi hidup di CLI, bukan dalam paket.

Perintah mana yang menunggu giliran:

Behavior Commands
Berjalan bersamaan (tidak pernah menunggu) status, , inspectlist-windows, search, get-property, get-value, , get-focused,wait-for
Menunggu giliran tetapi tidak pernah mengambil desktop set-value, , scroll-into-view/scroll --direction--to,record
Menunggu giliran dan mengambil desktop secara eksklusif invoke, click, drag, hover, scroll --wheel, touch, pen, focus, send-keys, screenshot

Baris tengah adalah yang layak dipahami. set-value, scroll-into-view dan scroll --direction/--to mendorong pola UIA daripada latar depan, sehingga tetap headless/sesi terkunci ramah dan tidak pernah memblokir siapa pun menggunakan desktop. Tetapi mereka mengubah apa yang ditunjukkan aplikasi, sehingga mereka menunggu di belakang giliran alur kerja lain daripada mengedit bidang atau menggulir daftar keluar dari bawah klik orang lain.

Dalam satu alur kerja, mereka tumpang tindih dengan pekerjaan bersama lainnya — itulah cara merekam recordset-value panggilan yang direkam. Mereka tidak mengabaikan penghalang maju alur kerja mereka sendiri: perintah sebelumnya DesktopExclusive dari alur kerja yang sama (a click, a screenshot) masih memblokirnya, persis seperti memblokir setiap perintah nanti, jadi klik dan mutasi yang mengikutinya tetap dalam urutan Anda menulisnya.

screenshot selalu mengantre untuk giliran eksklusif. Tidak setiap tangkapan mengganggu desktop — jendela yang terlihat biasa yang diambil melalui Windows Graphics Capture tidak — tetapi mesin memulihkan target jika diminimalkan, dan kembali ke latar depan saat pengambilan bingkai tidak tersedia atau --capture-screen membaca layar langsung. Kebutuhan tersebut hanya permukaan setelah penangkapan sedang berlangsung, sehingga perintah mengambil giliran di depan daripada menebak. Ketika menggabungkan beberapa jendela, itu menangkap mereka semua di bawah satu giliran eksklusif, sehingga gambar yang disimpan adalah satu momen yang konsisten daripada campuran sebelum dan sesudah. Pengodean dan penulisan file terjadi setelah desktop dirilis.

--capture-screen membutuhkan tepat satu jendela. Tangkapan layar langsung merekam apa pun yang sebenarnya ada di depan, dan hanya satu jendela yang bisa. Memilih jendela secara eksplisit dengan -w <hwnd> memberinya tepat satu wilayah — piksel di dalam batas jendela tersebut, termasuk dialog atau overlay yang terlihat di atasnya, yang merupakan alasan untuk membaca layar di tempat pertama. Ketika -a cocok dengan beberapa jendela tingkat atas atau milik tidak ada pilihan seperti itu, sehingga perintah gagal dengan invalid_arguments sebelum menangkap apa pun daripada melawan latar depan. Jalankan winapp ui list-windows -a <app> dan coba lagi dengan -w <hwnd>, atau jatuhkan --capture-screen untuk menyusun setiap jendela dari kontennya sendiri.

record membagikan gilirannya, sehingga input alur kerja yang sama dapat bersinggungan dengan pengambilan — itulah cara Anda merekam alur kerja yang mengendarai aplikasi. Dua peringatan:

  • record Tanpa id alur kerja adalah pemilik satu bidikan, sehingga memblokir setiap alur kerja lainnya selama seluruh durasinya. Untuk merekam dan mengklik pada saat yang sama, berikan kedua perintah yang sama WINAPP_UI_WORKFLOW_ID.
  • Pada host tanpa dukungan pengambilan bingkai, rekaman kembali ke PrintWindow, yang pemulihan bingkai kosongnya dapat memajukan jendela kapan saja. Di sana desktop ditahan untuk seluruh rekaman dan perintah mengatakan demikian dalam outputnya; bahkan input alur kerja yang sama akan menunggu.

Kesalahan yang mungkin Anda lihat: invalid_ui_workflow_id (variabel diatur tetapi kosong atau lebih dari 256 karakter), desktop_coordination_unavailable (status koordinasi tidak dapat dibaca dan tidak dapat dibangun kembali dengan aman, atau ditulis oleh yang lebih winappbaru ), queue_capacity_exceeded (64 perintah dari alur kerja lain sudah menunggu - batas menghitung pelayan asing langsung, bukan proses yang telah Anda mulai, sehingga entri milik perintah yang telah keluar atau telah dimatikan tidak menempati slot, dan perintah alur kerja Anda sendiri mengantre di belakang satu sama lain daripada terhadap batas ini), ui_turn_busy (yield sementara alur kerja Anda sendiri masih memiliki perintah yang berjalan), dan cancelled (Ctrl+C saat menunggu, keluar dari kode 130).

Melepaskan belokan lebih awal: winapp ui yield

Rahmat empat detik adalah fallback: ini menjaga desktop dicadangkan ketika Anda tidak dapat mengatakan dengan pasti bahwa Anda selesai. Ketika Anda dapat mengatakan demikian, katakanlah — yield tangan desktop segera alih-alih membuat orang lain menunggu kasih karunia yang tidak dibutuhkan.

$env:WINAPP_UI_WORKFLOW_ID = [guid]::NewGuid().ToString()

winapp ui invoke File -a notepad
winapp ui click "Save As..." -a notepad
winapp ui set-value txt-filename-a1b2 "notes.txt" -a notepad
winapp ui yield                      # done — a waiting workflow starts now, not in four seconds
  • Perintah satu bidikan tidak boleh mengatur id alur kerja sama sekali. Tanpa satu perintah, setiap perintah sudah merilis desktop saat selesai, dan tidak ada yang bisa dihasilkan.
  • Alur kerja multi-langkah harus menghasilkan setelah selesai, terutama ketika alur kerja lain mungkin menunggu. Biayanya satu perintah cepat dan menghapus kios empat detik dari orang lain.
  • Ini idempotensi. Menghasilkan dua kali, atau setelah anugerah telah terhenti, berhasil, dan melaporkan { "released": false } — itu adalah akhir normal dari skrip, bukan kegagalan.
  • Ini tidak pernah merilis giliran alur kerja lain. Jika orang lain memegang desktop, atau tidak ada yang melakukannya, itu adalah no-op.
  • Ini gagal dengan ui_turn_busy jika alur kerja Anda sendiri masih memiliki perintah yang berjalan atau diantrekan — rekaman, katakanlah. Melepaskan di bawahnya yang akan menyerahkan desktop ke tengah perintah, jadi tidak ada yang dirilis dan perintah yang sedang berjalan tidak terpengaruh. Tunggu atau hentikan, lalu hasilkan lagi.
  • Ini membutuhkan WINAPP_UI_WORKFLOW_ID. Tanpa salah satu itu gagal dengan invalid_arguments.
  • Tidak memerlukan aplikasi dan tidak ada pemilih: itu mengembalikan reservasi, bukan jendela, sehingga masih berfungsi setelah aplikasi ditutup.

Perintah menunggu dibangunkan oleh siapa pun yang merilis desktop daripada dengan polling untuk itu, sehingga antrean hampir tidak dikenakan biaya saat menunggu dan handoff segera. Setiap pelayan juga sesekali melakukan pemeriksaan ulang sendiri, yang merupakan apa yang memulihkan desktop ketika proses dimatikan dan tidak pernah menerbitkan apa pun: perintah di kepala antrean terlihat setiap setengah detik, dan perintah di belakangnya - yang tidak dapat berjalan sebelum kepala tetap melakukannya — setiap beberapa detik.

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. Tanpa filter kueri, hash menyediakan deteksi keusangan — jika elemen telah diganti, Anda mendapatkan: "Elemen mungkin telah berubah. Jalankan kembali inspeksi." Untuk kueri yang difilter, lihat Kueri terlingkup dan ditik.

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
winapp ui get-property Document -p FontWeight -a myapp --json     # document formatting

Nama properti peka huruf besar/kecil. Nama yang tidak diketahui gagal dengan invalid_arguments di bawah --json; hilangkan --property untuk mencantumkan properti, termasuk keenam atribut pemformatan teks di bawah ini. wait-for --property menggunakan nama peka huruf besar/kecil yang sama dan menolak nama yang tidak diketahui sebelum polling.

Pemformatan teks seluruh dokumen

Pemformatan dibaca di seluruh dokumen TextPattern elemen, bukan pilihan atau tanda sisipan saat ini. Bacaan tidak mengubah fokus atau pilihan.

Harta benda Nilai seragam (dikembalikan sebagai string)
FontWeight Berat numerik, seperti "400" (normal) atau "700" (tebal)
FontName Nama keluarga font, seperti "Courier New"
FontSize Ukuran dalam poin, seperti "15.5"
ForegroundColor Desimal Windows COLORREF (0x00BBGGRR), seperti "3678732" untuk RGB(12, 34, 56)
IsItalic "True" atau "False"
StrikethroughStyle Gaya dekorasi teks UIA numerik, seperti "0" (tidak ada) atau "1" (tunggal)

Angka menggunakan pemformatan invarian (titik desimal, terlepas dari lokal Anda). Setiap atribut dapat mengembalikan:

Nilai Arti dan langkah berikutnya
"Mixed" Pemformatan bervariasi dalam dokumen. Jangan perlakukan sebagai nilai seragam; perintah ini tidak mengkueri rentang teks individual.
"NotSupported" Penyedia TextPattern dokumen tidak melaporkan atribut ini. Periksa dukungan aksesibilitas aplikasi.
"Unavailable" Elemen tidak memiliki TextPattern. Gunakan inspect atau search untuk menemukan elemen teks/dokumennya.

Saat mencantumkan semua properti, properti dasar yang di-cache tetap tersedia jika tidak ada elemen langsung yang dapat diselesaikan, dan nilai pemformatan cacat dihilangkan tanpa membuang properti lain. Kelalaian ini dicatat sebagai peringatan. Minta properti pemformatan tertentu untuk mendapatkan kesalahan alih-alih kelalaian.

Kegagalan penyedia tetap kesalahan, bukan "Unavailable". Untuk stale_element, periksa aplikasi lagi dan coba lagi dengan pemilih saat ini.

Amplop JSON mencakup elementId, bernilai string , dan bernilai elementpropertiesstring . Properti yang ada, termasuk BoundingRectangle, pertahankan formatnya. Misalnya, bagian pemformatan adalah properties :

{
  "FontWeight": "700"
}

cuplikan layar

Ambil jendela atau elemen sebagai PNG.

winapp ui screenshot -a notepad                     # saves screenshot.png in cwd
winapp ui screenshot -a notepad --output my.png     # custom filename
winapp ui screenshot --quiet -a notepad -o my.png   # save without informational output
winapp ui screenshot -a notepad --json              # returns file path as JSON
winapp ui screenshot -w 131906                      # target specific HWND (+ its dialogs)
winapp ui screenshot txt-searchbox-e5f6 -a myapp          # crop to element bounds
winapp ui screenshot -w 131906 --capture-screen     # one screen region, with visible overlays in place; foregrounds window
winapp ui screenshot -a myapp --focus               # bring window to foreground first, then capture (default WGC path)

Tanpa pemilih elemen, pengambilan default menggabungkan beberapa jendela menjadi satu PNG komposit berlabel berdampingan, bukan file terpisah. -a menurut nama proses atau PID mencakup jendela aplikasi dan jendela miliknya. Kecocokan berbasis -a judul memilih satu jendela yang cocok ditambah jendela yang dimilikinya; -w secara eksplisit memilih satu jendela ditambah jendela yang dimilikinya, tidak setiap jendela dalam proses. Oleh karena itu, dialog atau tipsalat yang dimiliki dapat muncul sebagai panelnya sendiri bahkan ketika Anda secara eksplisit memilih HWND utama. Pemilih elemen dipangkas ke elemen tersebut alih-alih menyusun jendela.

--quiet menekan output informasi untuk tangkapan satu jendela dan komposit, termasuk jalur yang disimpan. Peringatan dan diagnostik kegagalan pengambilan tetap terlihat. Gunakan --json sebagai gantinya saat Anda memerlukan jalur file dan dimensi sebagai output terstruktur.

Dengan --on sandbox, --output memberi nama tujuan host. Output biasa yang berhasil dan --json melaporkan bahwa jalur host setelah gambar dikirimkan.

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 -w <hwnd> saat Anda memerlukan popup atau tipsalat yang terlihat di posisi layarnya, termasuk overlay yang tidak dimiliki oleh jendela target. Ini membaca wilayah layar jendela tersebut daripada menyusun panel berlabel, dan membawa jendela ke latar depan terlebih dahulu. Dengan -a, diperlukan tepat satu jendela yang cocok; jika beberapa jendela tingkat atas atau yang dimiliki cocok, gunakan winapp ui list-windows -a <app> dan coba lagi dengan -w <hwnd>. 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).

Karena DC layar menangkap apa pun yang sebenarnya ada di depan, --capture-screenmemverifikasi target mencapai latar depan segera sebelum menangkap dan gagal dengan foreground_not_target jika tidak (pencegahan pencurian fokus, prompt UAC, atau jendela lain yang mengaktifkan dirinya sendiri). Tidak ada gambar yang ditulis dalam kasus itu — sebelumnya perintah keluar 0 dan menyerahkan kembali gambar jendela yang salah. ui record --capture-screen menerapkan pemeriksaan yang sama sebelum bingkai pertama.

rekaman

Rekam jendela atau wilayah elemen ke H.264 MP4. Lebih suka positif --duration-sec untuk skrip tanpa pengawas. Tanpa durasi, perekaman berlanjut hingga Ctrl+C atau, untuk stdin yang dialihkan, baris baru atau EOF. Npm uiRecord dan targetRecord pembantu memerlukan bilangan bulat durationSec dari 1 hingga 86400; sinyal pembatalan mereka dibatalkan secara paksa daripada menyelesaikan rekaman dengan anggun.

# Record for 10 seconds
winapp ui record -a myapp --duration-sec 10 --fps 15 --output demo.mp4

# Add agent-readable frames
winapp ui record -a myapp --frames --duration-sec 10 --fps 10 --output evidence.mp4 --json

# Stop an unbounded recording through stdin
"" | winapp ui record -a myapp --json --output capture.mp4

# Include screen overlays and popups
winapp ui record -a myapp --capture-screen --duration-sec 5 --output with-popups.mp4

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.
  • --overwrite — Ganti output rekaman yang ada setelah proses baru selesai. Tanpa itu, output yang ada ditolak.
  • --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:

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

Pilih jalur output baru kecuali Anda ingin mengganti rekaman dengan --overwrite. Tanpa itu, baik video yang ada atau direktori yang dipasangkan .frames memblokir perekaman, bahkan ketika Anda menghilangkan --frames. MP4 sebelumnya tetap utuh jika penangkapan baru gagal. Pada penggantian yang berhasil, direktori bingkai sebelumnya dipertahankan sebagai <output-name>.frames.previous-<id>, bahkan jika rekaman baru menghilangkan --frames. Pertahankan bukti parsial dan ikuti yang dilaporkan recoveryHint sebelum mencoba kembali. Jika finalisasi MP4 gagal, bingkai yang dipertahankan dapat diterbitkan di bawah <output-name>.frames.partial-*. Artefak bingkai berisi konten layar yang tidak terenkripsi; menanganinya seperti cuplikan layar atau video.

Dengan --on sandbox, baik MP4 maupun direktori bingkai dikirimkan ke host, termasuk output default saat --output dihilangkan. Lihat Pengambilan sandbox untuk rekaman yang terganggu dan pengambilan seluruh desktop.

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 — Output rekaman sudah ada dan tidak dapat diganti di bawah opsi yang diminta.
  • 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 ikuti alur kerja overlay cuplikan layar untuk gambar diam. Lihat #646.

Memohon

winapp ui invoke SettingsCategory -a myapp --action select
winapp ui invoke AgreeCheckbox -a myapp --action toggle-on --json
winapp ui invoke SizeComboBox -a myapp --action expand
winapp ui invoke SubmitButton -a myapp

Gunakan --action saat pengujian harus melakukan operasi tertentu pada elemen yang dipilih. Ini tidak pernah mencoba pola lain atau leluhur yang dapat dipanggil, bahkan jika tindakan yang diminta gagal. Kontrol yang mendukung pemanggilan dan pemilihan akan dipilih, tidak dipanggil, dengan --action select. Dengan --action, simpul menargetkan tepat satu elemen; pemilih teks biasa atau AutomationId yang cocok dengan lebih dari satu elemen gagal ditutup dengan kode keluar bukan nol daripada bertindak pada kecocokan pertama, jadi berikan simpul dari inspect/search ketika nama ambigu.

Action Operation
invoke InvokePattern.Invoke
select SelectionItemPattern.Select
toggle TogglePattern.Toggle, tepat sekali
toggle-on / toggle-off Baca ToggleState; berhasil tanpa mengubah status yang sudah benar, jika tidak, alihkan dan verifikasi
expand / collapse ExpandCollapsePattern.Expand / Collapse

Untuk toggle-on dan toggle-off, status awal Indeterminate memungkinkan paling banyak dua transisi, memeriksa status setelah masing-masing. Status awal lainnya memungkinkan satu transisi. Jika status yang diminta tidak tercapai, perintah gagal daripada terus beralih. Verifikasi yang gagal dapat membuat kontrol berubah; baca ToggleState sebelum memutuskan apa yang harus dilakukan selanjutnya.

Tanpa --action, perilaku otomatis yang ada tidak berubah: coba InvokePattern, TogglePattern, SelectionItemPattern, lalu ExpandCollapsePattern (perluas), dengan coba lagi invokable-ancestor saat diperlukan.

Tindakan yang tidak didukung gagal dengan kode keluar bukan nol dan, dengan --json, kesalahan terstruktur pada stderr. Periksa kontrol yang dipilih dan pilih tindakan yang didukungnya, atau targetkan induk yang dimaksudkan secara eksplisit. JSON berhasil mencakup requestedAction dan performedAction; lihat referensi JSON.

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 pengiriman — warnings[] 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 list-windows -a myapp                              # use the main window's HWND below
winapp ui hover btn-info-a1b2 -a myapp; winapp ui screenshot -w <hwnd> --capture-screen  # hover then capture tooltip in place

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 bernama — enter/return, , tabesc/escape, space, backspace, , delete/delinsert, home, end,pageup/pgup , , pagedown/pgdn, up/down/left/right, f1–f16, apps, printscreen, . capslock
  • Urutan — beberapa token ditekan secara berurutan: down down enter.
  • Kombo pengubah — ctrl, 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 mentah — vk=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": "..." }
winapp ui get-value SearchBox -a myapp --json
winapp ui wait-for SearchBox -a myapp --value "" --timeout 5000

Bidang teks kosong yang berhasil dibaca mengembalikan "text": "", bukan label aksesibilitasnya. Konten khusus spasi putih juga dipertahankan di JSON. wait-for --value "" cocok dengan bidang kosong, apakah bidang tersebut segar atau dibersihkan setelah pengeditan. Untuk membaca label aksesibilitas, gunakan get-property --property Name.

Fokus

winapp ui focus txt-textbox-a4b1 -a notepad

Mengaktifkan jendela kontrol terpilih jika diperlukan, lalu memfokuskan kontrol. Pemilih diperlukan; gunakan -a <app> atau -w <HWND> untuk memilih target. Keberhasilan berarti jendela itu latar depan dan kontrol yang dipilih dikonfirmasi HasKeyboardFocus sebelum perintah dikembalikan. Perintah memungkinkan hingga 500 md agar kontrol melaporkan fokus; itu berhenti jika target menghilang atau kehilangan latar depan daripada mencoba mengambil fokus kembali. Dialog yang dimiliki di depan jendela utama tidak cukup: pilih kontrol dalam dialog jika itu adalah target Anda.

Perintah ini memerlukan desktop interaktif yang tidak terkunci dan tidak melewati batasan aktivasi Windows. Jika gagal dengan foreground_not_target, aktifkan jendela yang dimaksudkan secara manual dan periksa dialog pemblokiran sebelum mencoba kembali. Untuk focus_not_acquired, periksa UI saat ini dan pilih kontrol yang dapat difokuskan. Untuk stale_element, menemukan kembali target dengan inspect atau search. Pertahankan target yang sama --on pada perintah penemuan dan coba lagi.

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

winapp ui get-focused -a myapp
winapp ui get-focused -w <HWND> --json

Tampilkan elemen yang saat ini memiliki fokus keyboard di aplikasi yang dipilih, termasuk kontrol yang kepemilikan aplikasinya hanya tersedia melalui jendela induknya. Dengan -w, fokus harus berada di jendela tersebut, bukan jendela lain atau popup yang dimiliki dalam proses yang sama. Dengan -a, jendela lain dalam proses yang dipilih disertakan. Output JSON memiliki hasFocus:false ketika tidak ada elemen terfokus yang dapat diverifikasi sebagai milik target. Jika kueri fokus atau kepemilikan jendela gagal, perintah keluar dari bukan nol sebagai gantinya; coba get-focusedlagi , dan cari kembali jendela dengan list-windows jika telah ditutup.

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

hasil

Rilis UI alur kerja ini berubah lebih awal alih-alih menunggu tenggang menganggur empat detik. WINAPP_UI_WORKFLOW_IDMemerlukan ; tidak mengambil aplikasi dan tidak ada pemilih. Lihat Melepaskan belokan lebih awal.

winapp ui yield
winapp ui yield --json          # {"released": true} — or false when nothing was held

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.

Menggunakan mesin dari kode Anda sendiri

Semuanya winapp ui tersedia sebagai pustaka, sehingga Anda dapat mendorong otomatisasi yang sama dari pengujian atau alat tanpa keluar ke CLI:

Paket Apa yang ditambahkannya
Microsoft.Windows.SDK.BuildTools.WinApp.UIAutomation Inspeksi, pemilih, interaksi pola UIA, injeksi input, cuplikan layar
Microsoft.Windows.SDK.BuildTools.WinApp.UIAutomation.Recording Perekaman video ke MP4, ditambah bundel bingkai
var services = new ServiceCollection().AddLogging().AddWinAppUiAutomation().BuildServiceProvider();
var ui = services.GetRequiredService<IUiAutomation>();

var target = UiTarget.FromWindowHandle(myWindowHandle);
var save = await ui.FindSingleElementAsync(target, new UiSelector { Query = "Save" }, default);
await ui.InvokeAsync(target, save!, default);

Untuk tindakan deterministik, gunakan pengambilan kelebihan beban UiInvokeAction:

var selected = await ui.FindSingleElementAsync(
    target, new UiSelector { Query = "Save" }, requireUnique: true, default);
if (selected is null) throw new InvalidOperationException("Save was not found.");
UiInvokeActionResult result = await ui.InvokeAsync(target, selected, UiInvokeAction.Invoke, default);

requireUnique: true menolak teks ambigu alih-alih memilih kecocokan yang dapat dipanggil. Kecocokan AutomationId yang tepat lebih diutamakan daripada nama atau substring AutomationId; nama unik masih dapat memilih kontrol yang AutomationId-nya dibagikan. Untuk target cakupan aplikasi, pemeriksaan tersebut mencakup semua jendela aplikasi/miliknya. Gunakan -w <HWND> (atau target pustaka jendela eksplisit) untuk membatasi cakupan pilihan.

Ini mengembalikan Pattern dan PerformedAction dengan arti yang sama dengan hasil tindakan CLI. Berikan elemen yang dikembalikan oleh inspeksi atau pilihan, dengan simpul runtime atau AutomationId uniknya utuh. Tindakan eksplisit menolak identitas yang hilang atau ambigu daripada mengikat ulang berdasarkan nama dan jenis kontrol.

Untuk bacaan tercakup, atur UiSelector.Root ke lainnya UiSelector, ControlType ke nama jenis, dan ClassName ke kelas penyedia harfiah. Ini menggunakan predikat kueri yang sama dengan CLI. Hanya satu tingkat akar yang didukung: selector.Root.Root harus null. Akar berlapis melempar ArgumentException sebelum mencari jendela target. Gunakan AutomationId akar unik atau simpul alih-alih menumpuk pemilih akar. UiControlTypes.GetId(name) menyelesaikan nama jenis resmi dan dua alias yang didokumenkan, mengembalikan 0 untuk nama yang tidak valid. UiControlTypes.GetName(id) mengembalikan nama kanonis, atau Unknown(id) untuk ID yang tidak dikenal.

Saat meneruskan yang UiElement dipulihkan dari JSON ke GetTextAsync atau GetPropertiesAsync, simpan Selector dan WindowHandle. Pemilih simpul masih harus mengidentifikasi elemen asli; jika tidak ada lagi, bacaan ini dilemparkan UiElementNotFoundException alih-alih memilih elemen lain dengan AutomationId atau nama yang sama. Jalankan kueri asli lagi untuk merefresh hasilnya. Pembacaan tercakup juga menyebarkan kegagalan dari getter properti UIA umum dan memperoleh pola UIA daripada mengembalikan nilai null atau yang diambil sebelumnya.

Perekaman adalah paket terpisah sehingga proyek yang hanya memeriksa dan mendorong UI tidak menarik skiaSharp. Paket otomatisasi menargetkan dan net10.0-windowsnet10.0-windows10.0.19041.0; yang terakhir menambahkan Windows Graphics Capture, yang memungkinkan pengambilan windows yang dikomposisi screenshot GPU atau terkomposisi. Lihat README setiap paket di NuGet untuk API lengkap dan trade-off kerangka kerja target.

UiTarget.FromWindowHandleadalah titik masuk untuk kerangka kerja pengujian yang sudah memberi Anda jendela — misalnya MSTest.Windows.UIAutomation, yang merupakan UIA2 AutomationElement yang WindowTest.MainWindow Anda jembatani dengan MainWindow.Current.NativeWindowHandle.

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 Ikuti alur kerja overlay cuplikan layar untuk memilih jendela dengan -w <hwnd> --capture-screen
foreground_not_target dari --capture-screen Windows menolak aktivasi, sehingga tangkapan layar akan merekam jendela apa pun yang sebenarnya ada di depan Klik jendela target atau tutup jendela pencurian fokus dan coba lagi, atau letakkan --capture-screen
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 list-windows -a myapp # use the main window's HWND below
winapp ui set-value txt-searchbox-e5f6 "query" -a myapp; winapp ui screenshot -w <hwnd> --capture-screen
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)" }

# Read typed element state while preserving the legacy string property map
$property = winapp ui get-property "Counter Display" -a $pid --json | ConvertFrom-Json
if ($property.element.type -ne "Text") { throw "Unexpected type: $($property.element.type)" }
if ($property.element.isOffscreen) { throw "Counter is offscreen" }

Amplop JSON adalah:

  • inspect: { "depth", "interactive", "hideDisabled", "hideOffscreen", "windows": [...] }
  • search: { "matchCount", "hasMore", "matches": [...] }
  • wait-for: { "found", "waitedMs", "element"?, "timedOut" }
  • get-property: { "elementId", "element", "properties": { ... } }

Elemen yang ditik menggunakan type dan numerik x, , y, width, dan height. Geometri berada dalam piksel layar fisik. 0,0,0,0adalah persegi panjang UI kosong/tidak ditampilkan UI Automation dalam proyeksi ini; isOffscreen terpisah, sehingga elemen di luar layar masih dapat memiliki batas nonzero.

Setiap inspect --jsonwindows[] entri dan hasilnya status --json meliputi windowDpi, scale (windowDpi / 96), dpiAwareness, dan coordinateSpace: "physical-screen-pixels". Ini menjelaskan konteks DPI jendela target, bukan DPI monitor tanpa syarat: Windows melaporkan 96 untuk jendela yang tidak sadar, DPI sistem untuk jendela yang sadar sistem, dan DPI monitor saat ini untuk jendela yang sadar per monitor. Jika konteks HWND atau DPI tidak dapat dibaca, perintah gagal daripada menggantikan 96 secara diam-diam. Ketika status menyelesaikan proses sebelum memiliki jendela tingkat atas, hwnd adalah 0 dan bidang DPI dihilangkan hingga jendela ada. Untuk seluruh inspectproses , jendela target yang dipilih tetap gagal dengan cepat; jika popup selanjutnya menghilang setelah pohonnya dibaca, entrinya windows[] membawa dpiError dan menghilangkan bidang DPI sementara pohon jendela yang tersisa masih dikembalikan.

Lihat keterampilan references/ui-json-envelope.md yang dikirim winapp-ui-automation untuk contoh lengkap setiap amplop.

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