명령줄에서 실행 중인 Windows 애플리케이션을 검사하고 상호 작용합니다. AI 에이전트 및 개발자가 UI 테스트, 디버깅 및 자동화에 사용합니다.
개요
winapp ui Windows 앱 UI를 검사하고 상호 작용하기 위한 명령을 제공합니다.
UIA(Windows UI 자동화)를 사용합니다. WPF, WinForms, Win32, Electron 및 WinUI 3 등 모든 Windows 앱에서 작동합니다.
대부분의 명령은 UIA 패턴(입력 삽입 없음)을 통해 앱을 구동합니다. 예외는 실제 입력ui click/ui drag/ui hover을 삽입합니다. UIA 패턴이 구동할 수 없는 컨트롤 및 ui send-keys 시나리오에 대해 마우스 시뮬레이션 ui touch/ui pen 을 사용하고, 터치 및 펜/스타일러스 입력을 합성하고, 키보드 입력을 합성합니다.
Important
대화형 데스크톱 요구 사항(입력 주입 동사).click, hover, drag, touch, pen, scroll --wheel및 send-keys --via send-input OS 수준 입력을 합성하므로 포그라운드에 대상 창이 있는 잠금 해제된 대화형 데스크톱 이 필요합니다.
잠긴 워크스테이션 또는 보안 데스크톱(LogonUI/UAC)에서는 권한 상승/foreground_not_target사례와 no_interactive_desktop 는 별개로 빠르게 삽입하고 실패할 수 없습니다.
touch
/
pen 또한 창이 확인되지 않을 때(no_target) 거부합니다. 대상 창 외부의 좌표는 치명적 이 아닌 경고( warnings[] 텍스트 모드의 --json항목 또는 텍스트 모드의 경고 줄)이며 삽입은 마우스 동사와 일치하여 계속 진행됩니다. UIA inspectget-valuewait-forget-propertysearchinvokescroll --direction/--toset-valuescreenshot 패턴을 통해 앱을 구동하고 헤드리스/잠긴 세션에 친숙합니다. CI에서 UIA 패턴 동사를 선호합니다. 실제 입력이 필요한 시나리오에 대한 삽입 동사를 예약합니다. 또한 삽입하기 전에 제스처 동사는 대상 요소를 다시 확인하고 빈 공간에 입력을 착륙시키는 대신 애니메이션 효과를 주거나 재배치하는 경우 이를 거부 target_moved 합니다.
빠른 시작
# 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
앱 대상 지정
프로세스 이름별
winapp ui inspect -a notepad
winapp ui inspect -a slack # auto-picks visible window for multi-process apps
winapp ui inspect -a imageresizer # partial match: finds PowerToys.ImageResizer
창 제목별
winapp ui inspect -a "LICENSE - Notepad"
winapp ui inspect -a "Fix WinApp" # partial title match
PID별
winapp ui inspect -a 12345
HWND(안정적 - 탭/타이틀 변경 내용 유지)
# 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
안정적인 대상 지정을 위해 검색 -a 에 사용합니다-w. 여러 창과 일치하는 경우 -a 명령은 사용자가 선택할 HWND를 사용하여 나열합니다.
선택기
검사/검색 출력에 [brackets] 표시된 선택기를 사용하는 대상 요소입니다.
세 가지 유형의 선택기가 있습니다.
| 선택기 | 의미 | Example |
|---|---|---|
MinimizeButton |
AutomationId(고유할 때 표시됨 - 안정적이고 기본 설정) | winapp ui invoke MinimizeButton -a myapp |
btn-close-d1a0 |
의미 체계 슬러그(고유 AutomationId가 없는 경우 표시됨) | winapp ui invoke btn-close-d1a0 -a myapp |
Submit |
Name/AutomationId에 대한 일반 텍스트 검색(대/소문자를 구분하지 않는 부분 문자열) | winapp ui invoke Submit -a myapp |
AutomationId 선택기는 XAML에서 개발자 집합 식별자AutomationProperties.AutomationId 입니다.
AutomationId가 전체 UI 트리 inspect 에서 고유하고 search 선택기로 직접 표시되면 유지되는 레이아웃 변경, 지역화 및 트리 재구성이 유지됩니다.
슬러그 선택기 (예: btn-close-d1a0)는 고유한 AutomationId가 없을 때 생성됩니다.
형식: prefix-name-hash. 해시는 요소 ID의 유효성을 검사하지만 UI가 변경된 후 부실할 수 있습니다.
출력 형식 검사
이 inspect 명령은 색이 지정된 출력을 사용하여 요소 트리를 표시합니다(선택기(청록색 선택기, 녹색 이름, 회색 메타데이터).
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
각 줄의 첫 번째 단어 는 선택기입니다. 다른 ui 명령과 함께 사용합니다.
요소에 고유한 AutomationId가 있는 경우 직접 사용됩니다(예: TabViewNewTabButton).
고유한 AutomationId가 없으면 생성된 슬러그(예: tab-newtab-5f5b)가 사용됩니다.
의미 체계 슬러그
슬러그는 다음과 같은 형식 prefix-normalizedname-hash 을 사용합니다.
- 접두사 — 3자 형식 약어(btn, txt, chk, cmb, itm, tab, img, lbl, pn, win, grp, lnk, mnu 등)
- normalizedname - AutomationId(기본 설정) 또는 Name의 소문자 영숫자, 최대 15자
- 해시 - 요소 RuntimeId의 4자 16진수 해시(요소 ID 유효성 검사)
슬러그는 셸로부터 안전하며(특수 문자 없음), 고유하며 인수로 직접 사용할 수 있습니다. 해시는 부실 검색을 제공합니다. 요소가 교체된 경우 다음이 표시됩니다. "요소가 변경되었을 수 있습니다. 검사를 다시 실행합니다."
이름이나 AutomationId가 없는 요소는 접두사 + 해시(예: pn-c8a3)만 표시합니다.
여러 일치 항목 구분
출력의 inspect/search 슬러그는 고유하지만 레이아웃 변경에서 변경할 수 있습니다. 여러 항목이 일치할 때 일반 형식 이름 또는 텍스트에 사용합니다. 선택기가 모호한 경우 CLI는 모든 일치 항목을 해당 슬러그와 인쇄하므로 올바른 항목을 선택하고 해당 슬러그로 다시 실행할 수 있습니다.
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
일반 텍스트 검색
일반 텍스트를 사용하여 요소를 검색합니다. 특별한 구문은 필요하지 않습니다.
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
텍스트 검색이 여러 요소(예: 그룹, 단추 및 텍스트가 모두 같은 이름을 공유하는 SettingsExpander)와 일치하면 CLI는 호출 가능한 유일한 요소를 자동으로 선택합니다. 여러 항목을 호출할 수 있는 경우 슬러그가 있는 모든 일치 항목을 나열합니다.
호출할 수 없는 검색 결과(예: 단추 안의 TextBlock)의 경우 검색은 호출 가능한 가장 가까운 상위 항목(사용할 수 있는 부모 요소)을 invoke자동으로 표시합니다.
이는 모든 검색 선택기에서 작동합니다.
lbl-savechanges-a1b2 "Save changes" (120,40 80x20)
^ invoke via: btn-save-c3d4 "Save"
표면화된 선택기를 직접 사용할 수 있습니다.
winapp ui invoke btn-save-c3d4 -a myapp # invoke the parent Button
명령어
상태
앱에 연결하고 연결 정보를 표시합니다.
winapp ui status -a notepad
winapp ui status -a notepad --json
검사
UI 요소 트리를 봅니다. 출력은 계층 구조에 대해 2개의 공간 들여쓰기가 있는 의미 체계 슬러그를 보여 줍니다.
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
예제 출력(기본값):
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)
출력 예제(--interactive - 호출 가능한 요소만, 플랫 목록):
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)
요소는 다음과 같은 상태 표식을 표시할 수 있습니다.
-
[on]/[off]/[indeterminate]— 토글/확인란 상태 -
[collapsed]/[expanded]— 트리, 콤보 상자, 메뉴 항목에 대한 확장/축소 상태 -
[scroll:v]/[scroll:h]/[scroll:vh]- 스크롤 가능한 컨테이너(세로, 가로 또는 둘 다) -
[offscreen]— 요소가 화면에 표시되지 않습니다. -
[disabled]— 요소를 사용할 수 없습니다. -
value="..."— 편집 가능한 요소의 현재 텍스트 콘텐츠(Name과 다른 경우)
search
선택기와 일치하는 요소를 찾습니다. 출력은 의미 체계 슬러그를 보여줍니다.
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
예시 출력:
btn-minimize-d1a0 "Minimize" (1222,206 48x48)
btn-maximize-e2b1 "Maximize" (1270,206 48x48)
btn-close-d1a2 "Close" (1318,206 48x48)
출력에 표시된 슬러그(예: btn-minimize-d1a0)는 다른 명령과 함께 직접 사용할 수 있습니다.
winapp ui invoke btn-minimize-d1a0 -a notepad
get-property
요소에서 속성 값을 읽습니다. 패턴별 상태(ToggleState, Value, IsSelected 등)를 포함합니다.
winapp ui get-property btn-submit-7a90 -a myapp # all properties
winapp ui get-property chk-checkbox-b2c3 -p ToggleState -a myapp # checkbox state
winapp ui get-property txt-textbox-a4b1 -p Value -a myapp # current text value
winapp ui get-property cmb-combobox-d5e6 -p ExpandCollapseState -a myapp # expanded or collapsed
screenshot
창 또는 요소를 PNG로 캡처합니다. 여러 창이 있는 경우(예: 앱 + 열린 대화 상자) 각 창이 연결된 단일 PNG로 합성됩니다.
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)
대화 상자 또는 팝업이 열려 있으면 모든 창이 하나의 PNG로 합성되므로 단일 이미지에서 전체 UI 상태를 볼 수 있습니다.
기본 캡처 경로는 Windows 사용합니다. WGC(Graphics.Capture)에서 실제 DWM 복합 표면을 읽습니다. 둥근 모서리, 투명도를 유지하고 다른 windows 창이 가려지는 동안에도 작동합니다. WGC를 사용할 수 없는 경우(이전 Windows 빌드) CLI는 PrintWindow로 대체됩니다.
대상 창에서 소유하지 않은 팝업 메뉴, 드롭다운, 플라이아웃 또는 도구 설명 오버레이를 캡처해야 하는 경우에 사용합니다 --capture-screen .
--capture-screen 는 화면 DC에서 읽고 창을 포그라운드로 먼저 가져옵니다. 캡처 모드를 전환하지 않고 창을 포그라운드하려는 경우 사용합니다 --focus (예: 스크린샷이 사용자가 현재 보고 있는 것과 일치하는지 확인).
기록
대상 창(또는 요소의 영역)을 H.264 MP4 비디오에 기록합니다. 프레임은 Windows 그래픽 캡처(PrintWindow/화면-DC 대체 포함)를 통해 캡처되고 Media Foundation으로 증분 방식으로 인코딩되므로 녹화는 메모리의 전체 비디오를 버퍼링하지 않습니다.
기본 동작 (--duration-sec 0): 중지될 때까지 기록합니다. Ctrl+C를 대화형으로 사용하거나(프로그래밍 방식/에이전트 호출자의 경우) stdin 또는 닫는 stdin에 줄 바꿈을 작성하여 MP4를 정상적으로 중지하고 마무리합니다. 유효하고 재생할 수 있는 MP4는 항상 손상 없이 정상적인 중지에서 종료됩니다.
# Timed: record for 10 s at 15 fps
winapp ui record -a myapp --duration-sec 10 --fps 15 --output demo.mp4
# Unbounded (default): record until Ctrl+C, downscaled to max 1280px longest edge
winapp ui record -a myapp --max-edge 1280 --output capture.mp4
# Programmatic stop (agent/script): pipe a newline; the recorder stops and writes a valid MP4
"" | winapp ui record -a myapp --json --output capture.mp4
# Record a single element's region (fails with element_not_found if the selector doesn't match)
winapp ui record itm-chart-9f8e -a myapp --output chart.mp4
# Include screen overlays / popups (captures from screen DC; brings window to foreground)
winapp ui record -a myapp --capture-screen --duration-sec 5 --output with-popups.mp4
옵션:
-
--duration-sec N— N초 동안 기록합니다. 기본 값 0 = 중지될 때까지 레코드입니다. -
--fps N— 초당 대상 프레임(기본값 15)입니다. -
--max-edge N— 축소하여 가장 긴 가장자리가 최대 N픽셀(0 = 다운스케일 없음)입니다. -
--capture-screen- 화면 DC에서 캡처(오버레이/팝업 포함, 창 전경) -
--output <path>— 출력 MP4 경로입니다. 기본값은recording-<timestamp>-<guid>.mp4현재 디렉터리에 있습니다.
중지 메커니즘:
- 대화형: Ctrl+C (모든 플랫폼).
- 프로그래밍 방식/에이전트: 줄줄 (
"") 또는 닫기 stdin(EOF)을 작성합니다. 중지는 인코더가 준비되는 즉시 적용됩니다(첫 번째 프레임 캡처). 첫 번째 프레임이 래치되고 준비 시 즉시 적용되기 전에 도착하는 중지 신호는 유예 창이 없고 벽시계 지연이 없습니다.
캡처 모드 (JSON mode 필드에 보고됨):
-
wgc— Windows 그래픽 캡처(기본값, 창이 폐색된 동안 작동). -
printwindow— GDI PrintWindow(이 시스템/세션에서 WGC를 사용할 수 없는 경우 대체, 대신 화면 DC를 사용하도록 다시 실행--capture-screen). -
screen— 스크린 DC를 통해--capture-screen(오버레이/팝업 포함, 창이 포그라운드로 이동)
JSON 출력(--json):
-
stdout (최종 결과):
{ "path", "frames", "width", "height", "fileSize", "codec": "h264", "mode", "fps", "durationSec" } -
stderr (캡처가 시작될 때 내보내는 활동성 이벤트):
{ "event": "recording-started", "path", "fps", "durationSec" }
stderr의 활동성 이벤트를 통해 프로그래밍 방식 호출자는 최종 결과를 기다리지 않고 캡처 루프가 라이브 상태임을 알 수 있습니다. stdout의 최종 결과 JSON은 단일 클린 개체입니다.
오류 코드:
-
element_not_found— 선택기가 지정되었지만 일치하는 요소를 찾을 수 없습니다. 는 즉시 실패합니다(부분 파일이 기록되지 않음). -
ambiguous_selector— 일반 텍스트 선택기가 여러 요소와 일치합니다. 오류(또는inspect출력에서)에 표시된 제안에서 슬러그를 사용하여 특정 요소를 대상으로 합니다. -
invalid_arguments— 잘못된 옵션 값(예:--duration-sec -1또는> 86400)입니다.
알려진 제한 사항 - 창이 있는 팝업: WinUI/XAML 플라이아웃, 교육 팁, 도구 설명 또는 메뉴()와 같이 자체 최상위 창에서 렌더링되는 팝업 내에 있는 특정 요소 (Xaml_WindowedPopupClass선택기별)를 기록할 때 레코더는 팝업 대신 기본 주 창을 캡처하여 빈 프레임이나 부실 프레임을 생성할 수 있습니다.
전체 창을 기록하거나(선택기 생략) 팝업 스틸에 사용합니다winapp ui screenshot --capture-screen.
#646에서 추적됩니다.
프로그래밍 방식으로 요소를 활성화합니다(클릭 단추, 토글 확인란, 콤보 확장 상자).
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
순서대로 패턴을 시도합니다. InvokePattern → TogglePattern → SelectionItemPattern → ExpandCollapsePattern.
click
마우스 시뮬레이션을 사용하여 화면 좌표에서 요소를 클릭합니다. 이를 지원하지 InvokePattern 않는 컨트롤(예: 열 머리글, 목록 항목)에 사용합니다.
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
다른 입력 주입 동사와 마찬가지로 대상
click을 포그라운드로 가져오고 잘못된 창을 클릭하지 않고 빠르게 실패 합니다(no_interactive_desktop잠긴/안전한 데스크톱foreground_not_target에서 포커스를 전송할 수 없는 경우). 또한 단추 아래쪽 바로 앞에 있는 요소를 다시 확인합니다. 커서를 배치한 후 마지막 위치 검사를 수행하므로 클릭이 빈 공간에 착륙한 후 성공을 보고하는 대신 지속적으로 이동/애니메이션 효과를 주는 대상이 실패target_moved합니다. 보고된 성공은 단추가 다운되었을 때 대상이 여전히 제자리에 있었다는 것을 의미합니다.
드래그
한 지점에서 마우스 단추를 누르고, 다른 지점으로 drag <from> <to>이동한 다음, 각 엔드포인트가 요소 선택기(요소의 가운데에서/오른쪽으로 끌어오기) 또는 보고된 winapp ui inspect대로 화면 좌표 x,y 와 함께 놓습니다. 자유롭게 혼합하고 일치합니다(selector→selector, selector→coords, coords→coords).
앱에서 메시지의 WM_MOUSEMOVE 실제 스트림을 볼 수 있도록 중간 이동과 함께 사용합니다SendInput. 핸들, 슬라이더, 캔버스 그리기 및 끌어서 놓기에 다시 정렬/크기 조정에 사용합니다.
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
옵션:
-
--right- 왼쪽 단추 대신 마우스 오른쪽 단추로 끕니다. -
--hold-ms <ms>- 이동하기 전에 시작 단추를 누른 상태로 단추를 누릅니다(기본값: 0).<from> == <to>(이동 없음)을 사용하면 길게 누르거나 길게 누르는 제스처를 수행합니다. -
--dwell-ms <ms>- 해제하기 전에 이동한 후 대상에 유지됩니다(기본값: 0). 단추 위로 올라가기 전에 지속적인 호버(커서가 도착하는 즉시가 아닌) 래치에서 팔의 대상/병합 오버레이를 삭제 할 수 있습니다.
Bare
x,y는 동일한 공간winapp ui inspect/search보고서의 화면 좌표이며 선택기는 요소의 가운데로 확인됩니다. 먼저 검사하여 점을 선택합니다.
drag마찬가지로send-keys --via send-input대상을 포그라운드로 가져온 후 화면 좌표에 OS 전체를 삽입합니다. 포커스를 대상(예: 백그라운드 프로세스에서 포커스 도용 방지)으로 가져올 수 없는 경우 잘못된 창에서 포커스를 끌거나 창을 먼저 클릭하는 대신 명령이 실패합니다.(foreground_not_target예: 백그라운드 프로세스에서 포커스 도용 방지). 잠긴/안전한 데스크톱에서는 .와 함께no_interactive_desktop실패합니다. 각 요소 엔드포인트는 끌기 바로 전에 다시 확인됩니다. 계속 이동/크기 조정(애니메이션 대상)이면 부실 지점으로target_moved끌어오지 않고 명령이 실패합니다. (베어x,y엔드포인트는 다시 확인할 수 없으므로 as-is사용됩니다.)
터치
Windows 포인터 삽입 API를 사용하여 합성 터치 제스처를 삽입합니다. 연락처 앵커는 요소 선택기(요소의 중심 사용) 또는 (동일한 공간 winapp ui inspect 보고서)를 통한 --at 명시적 화면 좌표 x,y 입니다. 마우스 시뮬레이션에서 표현할 수 없는 탭/누름 조작 및 멀티 터치 제스처에 사용합니다.
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)
옵션:
-
--gesture <g>—tap(기본값),double-tap,long-press,swipe,stretchpinch. -
--at <x,y>- 명시적 시작점(화면 좌표). 기본적으로 선택기 요소 가운데로 설정됩니다. -
--to-point <x,y>— 에 대한 끝점입니다swipe.--direction보다 우선합니다. -
--direction <right|left|up|down>— 살짝 밀기 방향(기본값:right). 지정되지 않은 경우--to-point엔드포인트를 계산하기 위해 결합--distance됩니다. -
--distance <px>— 손가락으로 펴pinch/stretch지거나 살짝 밀기 거리를 픽셀 단위로 밉니다. -
--hold-ms <ms>— 해제하기 전에 연락처를 길게 누릅니다(길게 누르세요. 설정되지 않은 경우 기본값은 500mslong-press임). -
--duration-ms <ms>— 제스처 이동에 대한 글라이드 시간(살짝 밀기/손가락 모으기/스트레치, 기본값 300). -
--fingers <n>— 연락처 수(1~10, 기본값 1)입니다.pinch/stretch항상 2를 사용합니다.
주입 안전성.
touch는 0이 아닌 대상 창 핸들이 확인되고 해당 창이 포그라운드를 보유하지 않는 한 삽입을 거부합니다. 창을 확인할foreground_not_target수 없거나 포커스를 전송할 수 없는 경우 또는no_interactive_desktop잠긴/안전한 데스크톱에서 실패no_target합니다. 모든 좌표(요소 중심, 명시적--at--to-point/및 생성된 웨이포인트)는 대상 창 사각형에 대해 검사됩니다. 창 외부의 지점은 치명적이 아닌 경고(warnings[]텍스트 모드의 항목 또는 텍스트 모드의--json경고 선)로 표시되고 삽입은 여전히 진행됩니다. 이는 마우스 동사(drag/scrollclick/hover/)와 일치하며 창 외부 좌표에도 삽입됩니다.--fingers위의 10은 앞에서 거부됩니다.하드웨어 참고 사항입니다. Touch는 최신 가상 포인터 디바이스(
CreateSyntheticPointerDevice(PT_TOUCH))를 선호하며 레거시InitializeTouchInjection/InjectTouchInputAPI로 대체됩니다. 현재 디바이스/세션에서 삽입이 지원되지 않는 경우 명령은 잘못된 성공을 보고하는 대신 실제 Win32 오류 코드 (예: "지원되지 않음")를 표시합니다. 0이 아닌 종료를 "터치가 전달되지 않음"으로 처리합니다.원격 데스크톱/VM 세션 RDP(원격 데스크톱) 또는 일부 VM 세션에서 OS는 실제로 대상 앱에 도달하지 않고 가상 터치(종료 0)를 허용할 수 있습니다. 원격 세션이 검색되면
touch배달 불확실성 경고 (warnings[]입력 항목--json또는 텍스트 모드의 경고 줄)를 추가합니다. /exit 0은 ✅앱이 입력을 받은 것이 아니라 삽입 호출이 성공했음을 의미합니다. 중요한 경우 효과를ui screenshot/ui inspect확인합니다.
펜
Windows 가상 포인터 API를 사용하여 가상 펜/스타일러스 입력(탭 및 잉크 스트로크)을 삽입합니다(CreateSyntheticPointerDevice(PT_PEN); Windows 10 1809+). 요소 중심, 명시적 --at 점 또는 전체 --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
옵션:
-
--at <x,y>— 펜 접점(화면 좌표). 기본적으로 선택기 요소 가운데로 설정됩니다. 지정된 경우--path무시됩니다. -
--path "<x,y x,y …>"— 잉크 스트로크 경로를 공백으로 구분된x,y쌍으로 지정합니다(1포인트 경로는 탭). -
--pressure <0.0–1.0>— 펜 압력(기본값 0.5). -
--tilt-x <deg>/--tilt-y <deg>— 펜 기울기 각도 ,90 ~90(기본값 0). -
--eraser— 팁 대신 펜의 지우개 끝을 사용합니다. -
--duration-ms <ms>— 경로 전체에서 보간된 UPDATE 프레임으로 분산된 총 스트로크 이동 시간(밀리초)입니다(기본값: 웨이포인트당 ~10ms). 이를 사용하여 펜이 처음부터 끝까지 눈에 띄게 이동하는 속도를 제어할 수 있습니다.
주입 안전성. 마찬가지로
touch,pen0이 아닌 포그라운드 대상 창(no_target/no_interactive_desktopforeground_not_target/ )을 사용하지 않고 삽입을 거부하고 대상 창 사각형에 대해 모든 잉크 지점을 검사하여 마우스 동사와 일치하는 모든 잉크 지점을 치명적이 아닌 경고(warnings[]--json텍스트 모드의 경고 줄)로 표시합니다. 잘못된--pressure(0.0-1.0 외부) 또는 기울기(±90°외부)가 앞에서 거부됩니다.원격 데스크톱/VM 세션 펜 라우팅은 원격 데스크톱 대해 특히 불안정합니다. 삽입 호출은 성공(종료 0)을 보고할 수 있지만 펜 입력은 앱에 도달하지 않습니다. 원격 세션이 감지되면
pen배달 불확실성 경고(warnings[]--json텍스트 모드 또는 텍스트 모드의 경고 줄)를 추가하므로 ✅ 확인된 배달로 오인되지 않습니다. 로컬 대화형 데스크톱에서 펜 종속 흐름의 유효성을 검사합니다.
호버
마우스를 요소의 가운데로 이동하여 가리키기 효과(도구 설명, 플라이아웃, 시각적 상태)를 트리거합니다. 작은 흔들림으로 사실적인 마우스 이동을 사용한 SendInput 다음 구성 가능한 팽창 시간을 기다립니다.
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
옵션:
-
--dwell-time <ms>— 마우스로 가리키면 효과가 나타날 때까지 대기하는 시간(밀리초)(기본값: 800, 범위: 0-10000)
send-keys
가상 키보드 입력 보내기 - 에 대응하는 키보드입니다 click. UIA에는 키보드 삽입 패턴이 없으므로 Win32 계층으로 떨어집니다. 키보드 탐색(화살표, Tab, Enter, Esc), 바로 가기(ctrl+c, alt+f4) 및 원자성 쓰기가 아닌 set-value키 입력별 이벤트가 필요한 컨트롤에 입력하는 데 사용합니다.
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
키 문법 (공백으로 구분된 토큰, 따옴표 다중 토큰 문자열):
-
명명된 키 -
enterreturn/,,tab,escape/esc,space,delete/backspacedel,insert,home, ,/pguppageupend, ,f1pagedownpgdn///rightleft/downup, -appsf16printscreencapslock -
시퀀스 - 여러 토큰을 순서대로
down down enter눌렀습니다. -
한정자 콤보 —
ctrl,shift,alt조인win:+ctrl+shift+t,alt+f4. -
리터럴 텍스트 - 알려진 키가 아닌 토큰은 문자
hello별로 입력됩니다. 인접한 리터럴 단어는 둘 사이의 공간을 유지하므로 따옴표 붙은 구"Hello world"문은 축자로 입력됩니다(공간은 유지됨). 콤보로 구문 분석되지 않고 텍스트로만 포함+되거나a+b텍스트로C++입력되는 리터럴입니다. -
명시적 리터럴 이스케 이프 - 키
text=또는 한정자 이름과text=enter충돌하는 경우에도 토큰을 축자 형식으로 접두사로 지정합니다. Enter 키를 누르는 대신 "enter"라는 단어를 입력하고text=ctrl+a리터럴 문자열을 입력합니다. 이스케이프를vk=미러링합니다. 이스케이프된 값은 여전히 인접한 리터럴 단어(text=down low→ "down low")와 결합됩니다. 토큰은 공백으로 분할되고 인접한 리터럴이 단일 공백으로 다시 조인되므로 값 내에서text=백슬래시 이스케이프를 사용하여 공백,\t→ → 탭 → 줄 바꿈 →\n줄 바꿈 →\r\\리터럴 백슬래시 → 공백을 입력\s합니다.\n,\r각\r\n줄 바꿈(Enter/VK_RETURN)을 삽입하므로text=line1\nline2text=line1\r\nline2둘 다 줄 바꿈 하나를 입력합니다. 따라서text=a\s\sb"a b"(이중 공백)를 지정하고text=\shi선행 공간을 유지합니다. 인식할 수 없는 이스케이프(예:\x)는 그대로 남아 있습니다. -
전체 인수 리터럴(
--verbatim) - 전체 페이로드가 리터럴 텍스트인 경우 모든 토큰text=을 사용하여 이스케이프하는 대신 전달--verbatim합니다. 지정된 대로 전체 키 인수(명명된 키/콤보/vk=/text=해석 없음)를 정확하게 입력하고, 일반 경로와 달리 정확한 내부 공백(축소 없음)을 유지\s합니다. 따라서send-keys "down down enter" --verbatim단어를 입력하고send-keys "a b" --verbatim이중 공간을 유지합니다. 백슬래시 이스케이프는 모드에서--verbatim디코딩되지 않습니다(\s백슬래시 및 "s"로 형식화됨). 이스케이프된 컨트롤 문자가 필요한 경우 토큰을 사용합니다text=. -
원시 가상 키 (
vk=0xNN(16진수) 또는vk=NN이름 없는 키의 경우 (10진수)
옵션:
-
--target <selector>- 키를 보내기 전에 (UIA를 통해) 이 요소에 초점을 맞춥니다. 키가 없으면 키는 앱의 현재 포커스가 있는 요소로 이동합니다. -
--verbatim— 전체 키 인수를 리터럴 텍스트(키/콤보/vk=/text=구문 분석 없음)로 입력하고 정확한 공백을 유지합니다. 토큰text=별 이스케이프의 전체 인수 형식입니다. -
--via <transport>—post-message(기본값) 대상 창의 큐에 게시WM_CHARWM_KEYDOWN/WM_KEYUP/합니다. HWND 대상이며 UIPI를 무시합니다(무결성 수준에서 작동).send-input를 통해SendInputOS 전체를 삽입하고 포그라운드 창으로 이동합니다.
전송/알려진 제한 선택:
-
post-message는 UIPI를 무시하고 포그라운드되는 창에 의존하지 않기 때문에 기본값입니다. 제한: 하위 수준 후크(모든 창 큐의 해당 탭 입력 업스트림)를 통해WH_KEYBOARD_LL등록된 전역 바로 가기 키를 트리거할 수 없으며, 원시 키 상태를GetAsyncKeyState읽는 앱은 유지된 한정자를 관찰하지 못할 수 있습니다. 포그라운드 후 자동으로 확인되고 대상 스레드의 포커스가 있는 자식 창 (통해GetGUIThreadInfo)에 게시되므로 컨트롤이 별도의 자식 창인 클래식 Win32/WinForms 앱은 컨트롤을 수동으로 대상으로 지정하지 않고 키를 받습니다. WinUI 3 / UWP 앱에는 자식 HWND가 없는 창 없는 XAML 컨트롤이 있으므로 게시된WM_CHAR/WM_KEYDOWN컨트롤은 착륙할 수 없으며 삭제됩니다. 사후 메시지는 드라이브할 수 없습니다(명령이 경고하고 0을 종료함).--via send-input(WPF 창은 단일 HWND이며 내부적으로 포커스가 있는 요소로 키를 라우팅하므로 사후 메시지가 작동합니다.) -
send-input는 완전히 실제 입력(낮은 수준의 후크에서 볼 수GetAsyncKeyState있는 한정자)을 생성하지만, 상승된 프로세스에서 낮은 무결성(AppContainer/AppX) 대상으로 삽입할 때 포그라운드이고 UIPI에 의해 차단되는 모든 창으로 이동합니다. 실패를 보고하는 경우send-input대상은 상승되거나 AppX 앱일 가능성이 높습니다. 일치하는 무결성 수준에서 CLI를 사용post-message하거나 실행합니다. 안전 경비원send-input으로서 포커스를 가져올 수 없는 경우 잘못된 창에 입력하지 않고 삽입 및 실패하기foreground_not_target직전에 대상 창이 실제로 포그라운드에 있는지 확인합니다. 포커스를 맞추거나 창을 먼저 클릭합니다. 잠긴 데스크톱 또는 보안 데스크톱에서는 대신 세션 잠금을 해제하거나 UIA 패턴 동사(set-value,invoke)를 사용하여(삽입할 포그라운드 창이 없음) 실패no_interactive_desktop합니다. -
시스템 예약 콤보(
win+l, ,win+r,ctrl+shift+esc,ctrl+alt+del,alt+tabalt+f4,ctrl+esc, 고독win/printscreen한 , ...)는 OS 전체에서 전송할 때 대상만 사용하는 것이 아니라 OS/셸에서 작동합니다.send-input는 OS 수준에서 삽입하면 대상 창(invalid_arguments예:win+l세션 잠금)을 벗어나는 효과가 있으므로 기본적으로 오류를 거부하고 아무 것도 보내지 않습니다. 옵트인(opt in)을 전달--allow-system-keys하면 PowerToyswin+shift+v와 같은 글로벌 핫키를 구동하거나win+r(글로벌 하위 수준 후크가 OS 차원의 입력 스트림을 감시하여 삽입된 콤보가 실행되도록) 구동할 수 있습니다. 중단된 상태에서도--allow-system-keys차단된 상태로 유지되는 예외:win+l자동화에서 복구할 수 없는 워크스테이션LockWorkStation()을 잠그고(CI 및 원격 데스크톱 세션 중단), 플래그에ctrl+alt+del관계없이 삽입된 입력에서 Windows 삭제하는 SAS(보안 주의 시퀀스)이므로 잘못된 성공을 보고하는 대신 오류(invalid_arguments종료 1)가 발생합니다. 다른 콤보(alt+f4, ,ctrl+shift+esc,win+r...)는 플래그와 함께 허용됩니다. 호출자는 주의해야 합니다. 또는 특정 창에--via post-message시스템 콤보를 제공하려면 창 범위가 지정되고 영향을 받지 않습니다(게시된 경우 대상 창이 계속 닫히더라도 게시된win+lalt+f4항목은 무해합니다).
키 입력당 이벤트(KeyDown/ TextChanged):
-
명명된 키와 한정자 콤보(
down,enter, ,vk=0xNNctrl+shift+t)는 두 전송 모두에서 실제KeyDown(및KeyUp)를 발생시키고 불연속WM_KEYUPWM_KEYDOWN/(또는SendInput가상 키 이벤트)으로 전달됩니다. -
리터럴 형식 텍스트 (
hello)는 전송에 따라 다릅니다.-
--via send-input는 각 문자를 활성 키보드 레이아웃의 가상 키(및 Shift)에 매핑하므로 대상은 올바른 가상 키와 OS로 구성된(발생) 즉 문자당 하나의 전체 키 입력으로 정품KeyDown이 표시됩니다.TextChangedWM_CHAR현재 레이아웃에서 연결할 수 없는 문자(또는 Ctrl/AltGr 필요)는 유니코드 패킷으로 대체되므로 정확한 문자가 계속 표시됩니다. 키 입력별 충실도(예: 처리기가 키를 해제KeyDown하는 WinUI 3/WPFTextBox구동)가 필요할 때 사용합니다send-input.KeyDown일반(상승되지 않은) WinUI 3 테스트 호스트의 경우 포그라운드 창을 대상으로 하기 때문에send-input먼저 해당 창을 포그라운드로 가져옵니다(winapp ui focus/클릭). -
--via post-message는 문자당 단일WM_CHAR문자를 게시합니다(형식화된 텍스트에 대해서는 게시WM_KEYUP/WM_KEYDOWN하지않습니다. 명명된 키/콤보용으로 예약됨). 이는 문자KeyDown별로 발생하지 않습니다. 창의 포커스가 있는 자식 컨트롤로 자동으로 대상을 변경하므로 클래식 Win32/WinFormsWM_CHAR기반 편집 컨트롤이 텍스트를 표시합니다(발생TextChanged). 주의 사항: WinUI 3 / UWP / XAML 앱 (winapp의 기본 대상)에는 게시 된WM_CHAR/WM_KEYDOWN것을 무시하는 창이없는 컨트롤이 있으므로 명령이 성공을 보고하더라도 리터럴 텍스트나 명명 된 키 (Enter, digits, ...)가 도달하지 않습니다. 대상이 XAML처럼 보이고 여전히 0을 종료할 때 경고를 내보냅니다(PostMessage화재 및 잊어버리고 배달을 확인할 수 없습니다). WinUI 3/UWP/WPF 앱을 구동하는 데 사용합니다--via send-input. 클래식 Win32 컨트롤에 대한 예약post-message또는 무결성 수준에서 창 범위만 필요한 경우.
-
JSON 출력(--json): 결과는 hwnd 키가 전달된 --via post-message유효 창입니다. 이는 명령이 대상을 다시 지정할 때 확인된 포커스가 있는 자식 컨트롤이므로(반드시 최상위 -w//-a-e 창이 아님) 자동화에서 입력이 착륙한 위치를 정확하게 확인할 수 있습니다. 해당 유효 대상이 창 없는 XAML 호스트처럼 보이면 위의 배달 주의 사항도 항목(콘솔에 표시된 것과 동일한 권고)으로 warnings[] 표시되므로 ✅ 종료 0은 확인된 배달로 오인되지 않습니다.
set-value
프로그래밍 방식으로 편집 가능한 요소에 값을 설정합니다(키 입력 없음, 앱 포그라운드 없음). 대체 체인을 사용합니다.
- ValuePattern — TextBox, ComboBox, PasswordBox 및 가장 편집 가능한 컨트롤입니다.
- RangeValuePattern - 값이 숫자로 구문 분석되는 경우 숫자 컨트롤(Slider, ProgressBar)입니다.
-
LegacyIAccessible (
IAccessible::put_accValue) - ValuePattern을 노출하지 않는 TextPattern 전용 편집 컨트롤의 대체(예: 서식 있는 편집/Document작성 상자)입니다. 이렇게 하면 이러한 컨트롤을 읽을 수 있지만set-value읽을 수 없는get-value읽기/쓰기 간격이 닫힙니다.
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
세 가지 패턴 중 어느 것도 값을 set-value 설정할 수 없는 경우 마지막 수단으로 가리키는 send-keys 명확한 오류와 함께 실패합니다.
모든 리치 편집기가 프로그래밍 방식 집합을 지원하는 것은 아닙니다. LegacyIAccessible 대체는 접근성이 구현
IAccessible::put_accValue되는 컨트롤(네이티브 Win32 리치 편집 컨트롤 및 Chromium/Electron/WebView2 작성 화면)에서만 작동합니다. WinUI 3RichEditBox및 WPFRichTextBox프로그래밍 방식 값 설정을 지원하지 않습니다. 의도적으로 콘텐츠를 읽기 전용(텍스트 패턴, 설정 가능한 값 패턴 없음)으로 UI 자동화 노출하므로set-value쓸 수 없습니다. 이를send-keys위해 잠금 해제된 포그라운드 데스크톱이 필요합니다.
get-value
요소에서 현재 값을 읽습니다. 스마트 대체 체인을 사용합니다. TextPattern(RichEditBox, Document) → ValuePattern(TextBox, Slider) → SelectionPattern(ComboBox, RadioButton, TabView) → 이름(레이블).
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 focus txt-textbox-a4b1 -a notepad
보기로 스크롤
요소를 표시되는 영역으로 스크롤합니다.
winapp ui scroll-into-view itm-targetitem-c3d4 -a myapp
wait-for
요소가 나타나거나 사라지거나 값이 대상에 도달할 때까지 기다립니다.
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
스크롤
컨테이너 요소를 스크롤합니다. (세로 search scroll ) 또는 [scroll:v] (가로) 표식을 찾아 [scroll:h] 스크롤 가능한 컨테이너를 찾습니다.
# 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
옵션:
-
--direction <up|down|left|right>— 을 통해ScrollPattern증분 방식으로 스크롤합니다. -
--to <top|bottom>- 를 통해ScrollPattern시작/끝으로 이동합니다. -
--wheel <notches>— 휠 노치(detents)를 통해SendInput요소의 가운데에 마우스 휠 입력을 합성합니다1. = 1노치 업/어웨이,-1= 1노치 다운/쪽으로,3= 3노치 업. (각 노치는 사용하는 120개 단위SendInput의 WindowsWHEEL_DELTACLI는 120으로 조정됩니다.) 를 무시합니다ScrollPattern.
--direction은--to(는--wheel) 상호 배타적입니다. 정확히 하나를 전달합니다. 화면 좌표에 OS 차원의 입력을 삽입하기 때문에--wheel대상을 먼저 포그라운드로 가져오고 잘못된 창을 스크롤하는 대신 포커스를 전송할 수 없으면 실패합니다(foreground_not_target) .
집중하기
현재 키보드 포커스가 있는 요소를 표시합니다.
winapp ui get-focused -a myapp
list-windows
팝업 및 대화 상자를 포함하여 앱에 표시되는 모든 창을 나열합니다. 기본적으로 크기가 0인 제목 없는 창(보이지 않는 시스템 창)은 제외됩니다.
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
프레임워크 지원
| 프레임워크 | 검사 | search | 호출 | set-value | screenshot |
|---|---|---|---|---|---|
| WPF | ✅ 전체 트리 | ✅ 모든 속성 | ✅ 모든 패턴 | ✅ ¹ | ✅ |
| 윈폼 | ✅ | ✅ | ✅ | ✅ | ✅ |
| Win32 | ✅ | ✅ | ✅ | ✅ | ✅ |
| WinUI 3 | ✅ | ✅ | ✅ | ✅ ¹ | ✅ |
| Electron | ⚠️ 크롬 트리 | ⚠️ 제한됨 | ⚠️ 다양 | ⚠️ 다양 | ✅ |
| Flutter | ⚠️ 기본 | ⚠️ 기본 | ❌ 최소 | ❌ | ✅ |
1 set-value 은 ValuePattern/RangeValuePattern을 노출하는 모든 컨트롤과 접근성이 구현되는 TextPattern 전용 편집 컨트롤(LegacyIAccessible fallback)에서 작동합니다 IAccessible::put_accValue .
WinUI 3 RichEditBox 및 WPF RichTextBox 예외입니다. 읽기 전용 텍스트 패턴(설정 가능한 값 패턴 없음)만 노출하므로 의도적으로 프로그래밍 방식으로 설정할 수 없습니다. 입력하려면 (대화형 데스크톱 필요)를 사용합니다 send-keys .
Troubleshooting
| 오류 | 원인 | 솔루션 |
|---|---|---|
| "실행 중인 앱을 찾을 수 없음" | 앱이 실행되지 않거나 이름이 일치하지 않습니다. | 프로세스 이름 확인 또는 PID 사용 |
| "여러 창 일치" | 모호한 -a 값 |
나열된 옵션에서 사용 -w <HWND> |
| "여러 창이 있습니다." | 프로세스에 여러 창이 있습니다. | 특정 대상 지정에 사용 -w <HWND> |
| "선택기가 N 요소와 일치" | 모호한 레거시 선택기 | 출력에서 inspect 슬러그를 사용하거나 레거시 선택기에 추가 [0][1] |
| "요소가 변경되었을 수 있습니다." | 슬러그 해시가 현재 요소와 일치하지 않음 | 다시 실행 inspect 하거나 search 신선한 슬러그를 얻을 수 |
| "호출 패턴을 지원하지 않습니다." | 요소를 호출할 수 없습니다. | 요소를 사용하여 inspect 호출 가능한 자식 찾기 |
| "UIA 창을 찾을 수 없습니다." | UIA에서 프로세스를 볼 수 없습니다. |
list-windows HWND를 찾은 다음,-w |
| "창 크기가 0입니다." | 창 최소화 | 앱이 자동으로 복원됩니다. |
| 스크린샷에 없는 팝업/드롭다운 | 기본 캡처는 창당이며 소유되지 않은 오버레이를 포함하지 않습니다. | 플래그 사용 --capture-screen |
element_not_found 레코드 중 |
선택기가 지정되었지만 일치하는 요소가 없음 | 다시 실행 inspect 하거나 search 새 선택기를 가져옵니다. |
| 레코드 중에 WGC를 사용할 수 없음 | WGC 캡처 init가 실패했습니다. 자동 대체 없음 | GPU/드라이버 확인; 화면 DC 캡처에 동의하는 데 사용 --capture-screen |
일반적인 패턴
탐색 및 확인
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
텍스트 찾기 및 부모 호출
# 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
중복 요소 구분
winapp ui search '#Image' -a myapp; winapp ui invoke itm-image-a2b3 -a myapp
팝업 오버레이가 있는 스크린샷
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
검색, 클릭 및 확인
winapp ui inspect -a myapp --interactive; winapp ui invoke btn-submit-7a90 -a myapp; winapp ui screenshot -a myapp
파일 대화 상자 상호 작용
파일 열기/저장 대화 상자는 UIA가 지원하는 표준 Windows 대화입니다.
# 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>
특정 대화 상자의 실제 슬러그를 검색하는 데 사용합니다 inspect -w <dialog-hwnd> --interactive .
체인에 대한 이유 ; (아님 &&)
네이티브 CLI가 stderr에 쓰거나 ANSI 이스케이프 시퀀스를 사용할 때 PowerShell의 && 연산자가 중지할 수 있습니다. 대신 각 ; 명령을 무조건 실행하고 이 교착 상태를 방지합니다. 에이전트 워크플로에 더 적합합니다. 일반적으로 호출에 0이 아닌 종료가 있더라도 스크린샷을 실행하려고 합니다.
CI 테스트 패턴
스모크 테스트 및 UI 유효성 검사에 CI 파이프라인(GitHub Actions, Azure DevOps)에서 winapp ui 명령을 사용합니다.
wait-for
--property 을 사용하여 --value 어설션으로 작동합니다. 시간 제한 시 종료 코드 1을 반환하여 CI 단계가 자동으로 실패합니다.
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
다음을 사용하여 요소 상태를 어설션합니다. wait-for
wait-for --value 요소의 값이 예상 문자열과 일치할 때까지 폴링합니다.(TextPattern → ValuePattern → SelectionPattern → Name)과 동일한 스마트 대체 get-value 를 사용합니다. 일치 시 종료 코드 0을 반환하고, 시간 제한 시 코드 1을 종료하여 CI 친화적인 어설션으로 만듭니다. 대신 특정 UIA 속성을 확인하는 데 사용합니다 --property .
# 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
JSON 출력을 사용하여 어설션
더 복잡한 어설션을 위해 PowerShell 또는 jq와 함께 사용합니다 --json .
모드에서
search종료 코드 계약wait-for--json: 일치하는 요소가 없거나 대기 시간 초과(searchwait-for)가 없는 경우 명령은 완전히 구문 분석 가능한 결과 봉투를 stdout({ "matchCount": 0, ... }또는{ "found": false, "timedOut": true, ... })에 쓰고 종료 코드 1을 반환합니다. Stderr는 모드에서--json비어 있습니다(로거 출력은 표시되지 않습니다). 봉투 필드의 분기 또는 인체공학적 요소에$LASTEXITCODE따라 분기합니다.
# 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)" }
전체 스모크 테스트 예제
# Launch
$app = winapp run .\build-output --detach --json | ConvertFrom-Json
# Verify app loaded
winapp ui wait-for "Main Page" -a $app.ProcessId -t 30000
# Interact and assert
winapp ui invoke "Add Item" -a $app.ProcessId
winapp ui set-value "Item Name" "Test Item" -a $app.ProcessId
winapp ui invoke "Save" -a $app.ProcessId
winapp ui wait-for "Test Item" -a $app.ProcessId -t 5000 # assert item appeared in list
winapp ui wait-for "Save" -a $app.ProcessId --gone -t 3000 # assert save dialog closed
# Visual verification
winapp ui screenshot -a $app.ProcessId -o smoke-test.png
Windows developer