Автоматизация пользовательского интерфейса

Проверьте и взаимодействуйте с запущенными приложениями Windows из командной строки. Используется агентами ИИ и разработчиками для тестирования пользовательского интерфейса, отладки и автоматизации.

Обзор

winapp ui предоставляет команды для проверки и взаимодействия с Windows интерфейсами приложений. Использует Windows модель автоматизации пользовательского интерфейса (UIA). Работает с любым приложением Windows — WPF, WinForms, Win32, Electron и WinUI 3. Большинство команд управляют приложением с помощью шаблонов UIA (без внедрения входных данных). Исключения внедряют реальные входные данные: ui click/ui hover/ui dragиспользуйте имитацию мыши,ui touch/ui pen синтезирует сенсорный ввод и перо или перо или перо и перо и ui send-keys синтезирует входные данные клавиатуры — для элементов управления и сценариев, которые не могут выполняться шаблонами UIA.

Important

Требование к интерактивному рабочему столу (вводные команды).click, hover, drag, touch, penscroll --wheel, и send-keys --via send-input синтезирование входных данных на уровне ОС, поэтому им нужен разблокированный интерактивный рабочий стол с целевым окном на переднем плане. На заблокированной рабочей станции или защищенном рабочем столе (LogonUI/UAC) они не могут внедряться и завершаются сбоем no_interactive_desktop (отлично от повышения илиforeground_not_target случаев). touch / penкроме того, если окно не разрешается (); координата вне целевого окна является no_target (warnings[]запись в --jsonтекстовом режиме или строка предупреждения в текстовом режиме) и внедрение по-прежнему продолжается — в соответствии с командами мыши. Все остальное — inspect, search, get-valueset-valuewait-forinvokeget-property— scroll --direction/--to управляет приложением с помощью шаблонов UIA и не поддерживает сеанс с головой и заблокированным сеансом. screenshot является исключением из неинтерактивных команд: он принимает монопольный поворот и его захват может потребоваться интерактивный рабочий стол, так как подсистема восстанавливает свернутый целевой объект и возвращается к переднему плану, когда запись кадров недоступна или --capture-screen используется. Предпочитать команды UIA-pattern в CI; резервирует команды внедрения для сценариев, которые действительно нуждаются в реальных входных данных. Перед внедрением команды жестов также повторно разрешают целевой элемент и отказываются target_moved , если он по-прежнему анимирует или перемещает, а не приземливает входные данные в пустом пространстве.

Краткое руководство

Запустите winapp ui --help для основного цикла: inspect -a <app> --interactive чтобы узнать, что можно действовать или invokeset-value действовать, а get-value также проверять результат. В каждой --help команде показаны примеры. Неизвестная команда, например winapp ui dump, завершает работу с кодом 1 и предлагает ближайшие команды (как ошибка JSON при suggestions передаче --json).

# 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

Запуск автоматизации пользовательского интерфейса в песочнице Windows

Чтобы сохранить автоматизацию на рабочем столе, добавьте --on sandbox в команды запуска и пользовательского интерфейса:

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

--detach возвращается после запуска; без него run ожидает завершения работы приложения. Следите --on sandbox за каждой гостевой командой, включая те, которые используют пиД или дескриптор окна. Ознакомьтесь с Windows выполнение песочницы для требований клиента, кратких изменений в настройке и повторном подключении фокуса, координации рабочих процессов и доставки выходных данных узла.

Области и типизированные запросы

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
winapp ui invoke Open -w <dialog-HWND> --type Button
winapp ui set-value "Text editor" "hello" -a notepad --type Document

Эти команды принимают необязательные фильтры в селекторе элементов: inspect (с селектором), get-propertyrecordset-valueinvokeclickwait-forfocushoverget-valuesearchscroll-into-viewscreenshotscrolltouch, и .pen drag (два селектора) и send-keys --target не. Селектор и каждый предоставленный фильтр должны соответствовать одному элементу. Фильтры сужают селектор, поэтому inspectscreenshot, и record, селектор которого является необязательным, завершается ошибкой invalid_arguments при выполнении заданных фильтров без одного. Для touch и pen, фильтры нуждаются в селекторе; они не могут быть объединены с --at или --path (invalid_arguments):

  • --root <selector> выполняет поиск только потомков одного уникально совпадающего корня, никогда не самого корня. Используйте automationId или slug из inspect диамбигуата. Корневой каталог, соответствующий нескольким элементам, завершается сбоем ambiguous_selector, даже если можно вызвать одно совпадение. Отсутствующий корень не создает совпадений. Когда корневой каталог найден, запросы не выполняют поиск несвязанных всплывающих окон, даже если не совпадают потомки. Запросы не ограничиваются глубиной inspectотображения.
  • --type <control-type> соответствует типу элемента управления UIA, игнорируя регистр. Единственными псевдонимами являются TextBox → Edit и TextBlock → Text. Неизвестные имена (включая числовые идентификаторы и выражения подстановочных знаков) завершаются ошибкой invalid_arguments.
  • --class-name <literal> соответствует всему UIA ClassNameпоставщика, игнорируя регистр. Это не подстрока, подстановочный знак или регулярное выражение. Используется get-property --property ClassName для обнаружения значения поставщика. Имя класса не равно типу элемента управления UIA.

Отфильтрованные запросы используют представление элементов управления UIA, то же представление, что и в представлении inspect. Узлы поставщика, предоставляемые только в необработанном представлении, не возвращаются; используется inspect для поиска содержащего элемента управления и его селектора.

Поддерживаются все 41 официальных типов: Button, CalendarCheckBoxComboBoxEditHyperlinkImageListItemListMenuMenuBarMenuItemProgressBarRadioButtonScrollBarSliderSpinnerStatusBarTabTabItemTextToolBarToolTipTreeTreeItemCustomGroupThumbDataGridDataItemDocumentSplitButtonWindowPaneHeaderHeaderItemTableTitleBarSeparatorSemanticZoomAppBar

wait-for снова разрешает корневой селектор на каждом опросе, поэтому корневой элемент может появиться после запуска команды. При --goneэтом отсутствующий корень означает отсутствие соответствующего потомка; неоднозначный корень является ошибкой, а не успешной. Прерванный поиск не является доказательством исчезновения: если элемент удаляется во время поиска или замены перед --value чтением, следующий опрос проверяет снова; другие ошибки поиска или чтения ошибок завершается ошибкой. -w <HWND> ограничивает корневое обнаружение деревом UIA этого окна. С -aпомощью корневого обнаружения также можно найти всплывающие окна приложения. Точные корневые совпадения AutomationId имеют приоритет над совпадениями подстроки во всех этих окнах; Несколько точных совпадений по-прежнему завершаются ошибкой ambiguous_selector.

Корневой слизь выбирает этот элемент, даже если другое окно имеет тот же идентификатор AutomationId. Если выбранный корень заменен, старый слизь больше не соответствует; используйте корневой каталог AutomationId или имя, если требуется выполнить опрос.

При наличии фильтров каждая команда, за исключением search сбоя ambiguous_selector , если остается несколько элементов; сузите фильтры или используйте уникальный слизь. Команды, действующие на количество элементов, совпадают в каждом окне поиска, поэтому соответствующий элемент управления в собственном диалоговом окне также делает селектор неоднозначным. Точные совпадения AutomationId сохраняют приоритет над совпадениями подстроки в отфильтрованной области. Опущение всех трех параметров сохраняет существующее поведение запроса.

Координация параллельных рабочих процессов пользовательского интерфейса

Windows имеет только одно окно переднего плана, один фокус клавиатуры, один курсор и один входной поток. Когда два winapp ui рабочих процесса выполняются одновременно на одном рабочем столе, они могут украсть фокус друг с другом, закрыть меню другого только что открывшегося или переместить целевой объект из-под ожидающего щелчка.

Арбитраж всегда включен. Каждая winapp ui команда, которая прикасается к физическому рабочему столу, принимает поворот, без настройки и нет способа отключить его, поэтому два агента никогда не могут вводить в окна друг друга. Команды только для чтения выполняются одновременно. Одним из исключений является процесс, который не может получить доступ к папке координации winapp, например песочнице агента, которая блокирует %USERPROFILE%\.winapp: ее команды по-прежнему выполняются, но не выполняя повороты, и выводить предупреждение (за исключением --json или --quiet).

Непрерывность между командами включена. По умолчанию каждая команда — это автономный один снимок: он ожидает свою очередь, выполняет свою работу и немедленно освобождает рабочий стол. Чтобы сохранить рабочий стол в нескольких командах, предоставьте им один и тот же идентификатор рабочего процесса:

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

Что вам необходимо знать:

  • Идентификатор рабочего процесса называет один логический рабочий процесс — не обязательно целый агент, а не обязательно одно приложение. Используйте то же значение для сотрудничества команд (запись и щелчки, которые она должна записать); используйте разные значения для независимых рабочих процессов, даже если один агент запускает оба.
  • Без идентификатора каждая команда является независимой однозастрелной. Он по-прежнему арбитраж, но он не дает благодати и руки рабочему столу от момента, когда он заканчивается. Две команды no-id являются отдельными рабочими процессами даже при запуске из одной оболочки.
  • Свежие оболочки и адаптивные узлы должны внедрять то же значение. Если каждая команда выполняется в новой оболочке — то, как большинство вызовов инструментов агента работает, единственное, что может сгруппировать их, является явной WINAPP_UI_WORKFLOW_ID передачей в каждый взаимодействующий вызов.
  • Четырехсекундная благодать защищает жесткие всплески, а не модели рассуждений. Рабочий процесс с идентификатором сохраняет свою очередь до тех пор, пока следующая команда начинается в течение четырех секунд. Это охватывает команды обратно в один скрипт; Он намеренно истекает, пока модель думает. Это резервный вариант, когда вы не можете сказать, что вы закончили - когда вы можете, бежать winapp ui yield , а не ждать его.
  • Адаптивные рабочие процессы должны выполнять повторную проверку, повторную проверку и воспроизведение. После того, как другой рабочий процесс может использовать рабочий стол, поэтому повторно откройте меню, повторно устраните элемент, а затем выполните действия. Отправляйте известные комплексные последовательности как один жесткий сценарий, а не удерживайте рабочий стол, пока вы думаете.
  • Упорядочивание — это сходство владельцев, а затем FIFO среди других. Хотя рабочий процесс активен или находится внутри его благодати, он может продолжать выдавать команды, даже если другие рабочие процессы уже ожидают. После истечения winapp ui yield срока действия или его льготы рабочие процессы ожидания обслуживаются в строгом порядке прибытия. Непрерывные действия по одному рабочему процессу могут отложить другие на неопределенный срок.
  • Нет жесткой крышки. Длинный скрипт, несвязанная запись или цикл сбоя может блокировать другие мутирующие рабочие процессы.
  • Отмена или завершение процесса — это восстановление для зависающего рабочего процесса. Ожидающие команды печатают состояние после одной секунды и могут быть остановлены с помощью Ctrl+Cкоторого завершается 130.
  • Взаимодействуют только совместимые двоичные файлы. Старые winapp сборки предопределяют эту функцию и не координируются. Код, вызывающий пакеты NuGet модель автоматизации пользовательского интерфейса непосредственно за пределами этой гарантии, полностью — координация находится в интерфейсе командной строки, а не в пакетах.

Какие команды ожидают поворота:

Behavior Commands
Выполняется одновременно (никогда не ожидается) status, list-windows, inspectsearchget-propertyget-valueget-focusedwait-for
Ожидает поворота, но никогда не принимает рабочий стол set-value, , scroll-into-viewscroll --direction/--torecord
Ожидает поворота и принимает рабочий стол исключительно invoke, click, draghoverscroll --wheeltouchpenfocussend-keysscreenshot

Средняя строка является одной из достойных понимания. set-value, scroll-into-view и scroll --direction/--to диск шаблонов UIA, а не переднего плана, поэтому они остаются без головы/заблокированных сеансов дружественными и никогда не блокируют кого-либо использовать рабочий стол. Но они изменяют то, что приложение показывает, поэтому они ожидают от поворота другого рабочего процесса, а не редактирования поля или прокрутки списка из-под щелчка кого-то другого.

В одном рабочем процессе они перекрываются с другой общей работой— то есть record как записывает вызовы set-value , которые она записывает. Они не игнорируют собственный барьер вперед рабочего процесса: более ранняя DesktopExclusive команда того же рабочего процесса (a, ascreenshotclick) по-прежнему блокирует их, точно так же, как она блокирует каждую более позднюю команду, поэтому щелчок и мутация, которая следует за ним, остается в порядке, который вы написали.

screenshot всегда очереди для монопольного поворота. Не каждый захват беспокоит рабочий стол — обычное видимое окно, записанное с помощью Windows графического захвата, не делает , но подсистема восстанавливает целевой объект, если он свернут, и возвращается к переднему плану, когда запись кадров недоступна или --capture-screen считывает динамический экран. Эти потребности требуют только поверхности после того, как выполняется захват, поэтому команда принимает поворот вперед, а не угадывание. Когда он составит несколько окон, он захватывает их все под одним монопольным поворотом, поэтому сохраненный образ является одним согласованным моментом, а не сочетанием до и после. Кодирование и запись файла происходят после выпуска рабочего стола.

--capture-screen требуется ровно одно окно. Запись с экрана в прямом эфире записывает все, что на самом деле на самом деле, и может быть только одно окно. Выбор окна явным образом дает -w <hwnd> ему ровно один регион — пиксели внутри границ этого окна, включая любое диалоговое окно или наложение на него видимо, что является причиной чтения экрана в первую очередь. При -a совпадении нескольких окон верхнего уровня или собственных окон нет такого выбора, поэтому команда завершается сбоем invalid_arguments перед захватом ничего, а не борьбы с передним планом. Запустите winapp ui list-windows -a <app> и повторите попытку с -w <hwnd>помощью или удалите --capture-screen их в состав каждого окна из собственного содержимого.

record делится своей очередью, поэтому входные данные одного рабочего процесса могут взаимодействовать с записью— это то, как вы записываете рабочий процесс, управляющий приложением. Два предостережения:

  • Без record идентификатора рабочего процесса является владельцем одного снимка, поэтому он блокирует каждый другой рабочий процесс в течение всего времени. Чтобы записать и щелкнуть одновременно, предоставьте обе команды одинаково WINAPP_UI_WORKFLOW_ID.
  • На узле без поддержки отслеживания кадров запись возвращается в PrintWindow, восстановление пустого кадра которого может выходить на передний план окна в любой момент. Там рабочий стол хранится для всей записи, и команда говорит так в выходных данных; даже входные данные одного рабочего процесса будут ждать.

Ошибки могут появиться: invalid_ui_workflow_id (переменная задана, но пуста или более 256 символов), desktop_coordination_unavailable (состояние координации является непрочитаемым и не может быть безопасно перестроено или записано более новым winappqueue_capacity_exceeded ), (64 команды из других рабочих процессов уже ожидают— ограничение учитывает динамических внешних официантов, а не запущенные процессы, поэтому записи, принадлежащие командам, завершившимся или убитым, не занимают слот, и собственные команды рабочего процесса в очереди друг за другом, а не против этого ограничения), ui_turn_busy (yieldв то время как собственный рабочий процесс по-прежнему выполняет команду), и cancelled (CTRL+C во время ожидания, выхода кода130).

Выпуск поворота рано: winapp ui yield

Четырехсекундная льгота является резервным вариантом: он сохраняет резервную запись рабочего стола, когда вы не можете сказать наверняка, что вы завершены. Когда вы можете сказать так, скажем так - yield руки на рабочем столе немедленно вместо того, чтобы сделать все остальные ожидать благодать никто не нуждается.

$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
  • Команды с одним снимком не должны задавать идентификатор рабочего процесса вообще. Без одной команды каждая команда уже освобождает рабочий стол, когда она завершается, и нет ничего, чтобы дать.
  • Многофакторные рабочие процессы должны давать, когда они завершаются, особенно если другие рабочие процессы могут ждать. Это стоит одна быстрая команда и удаляет четырехсекундный стойл со всех остальных.
  • Это идемпотентно. Получение дважды или после того, как благодать уже провалилась, успешно и сообщает { "released": false } — это обычный конец скрипта, а не сбой.
  • Он никогда не освобождает очередь другого рабочего процесса. Если кто-то другой держит рабочий стол, или никто не делает, это no-op.
  • Он завершается ошибкой, ui_turn_busy если собственный рабочий процесс по-прежнему имеет команду, запущенную или в очереди, — запись, скажем. Выпуская под ним, который будет передавать рабочий стол в середине команды, поэтому ничего не освобождается и выполнение команды не влияет. Подождите или остановите его, а затем снова вернитесь.
  • Для этого требуется WINAPP_UI_WORKFLOW_ID. Без него не удается invalid_arguments.
  • Он не принимает ни приложения, ни селектора: он возвращает резервирование, а не окно, поэтому он по-прежнему работает после закрытия приложения.

Команда ожидания проснулась тем, кто освобождает рабочий стол, а не опросы для него, поэтому очередь стоит почти ничего, пока она ожидает и раздаток немедленно. Каждый официант также выполняет повторную проверку по своему усмотрению. Это то, что восстанавливает рабочий стол при убийстве процесса и никогда не публикует ничего: команда в голове очереди выглядит каждые половину секунды, и команды за ним , которые не могут выполняться перед головой в любом случае — каждые несколько секунд.

Целевые приложения

По имени процесса

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 search Seven -a calculator  # hosted app: uses the frame window that hosts it

Некоторые упакованные приложения (например, калькулятор) не имеют собственного окна; другой процесс размещает кадр. Если соответствующий процесс (по имени или PID) не имеет видимого окна, -a использует кадр, в котором размещается его содержимое. Если нет (например, приложение по-прежнему запускается), -a предназначено для процесса, поэтому wait-for продолжает искать, пока не появится его окно.

По заголовку окна

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

By 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] результатах проверки и поиска. Существует три типа селекторов:

Selector Значение 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 — это идентификаторы наборов разработчиков (AutomationProperties.AutomationId в XAML). Когда automationId является уникальным для всего дерева пользовательского интерфейса и inspectsearch отображает его непосредственно в качестве селектора— они сохраняют изменения макета, локализацию и реструктуризацию деревьев.

Селекторы slug (например, btn-close-d1a0) создаются при отсутствии уникального идентификатора automationId. Формат: prefix-name-hash. Хэш проверяет удостоверение элемента, но может оказаться устаревшим после изменений пользовательского интерфейса.

Проверка формата выходных данных

В 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, он используется напрямую (например, TabView, NewTabButton). Если уникальный automationId не существует, используется созданный слизь (например, tab-newtab-5f5b).

Семантические слизи

Slugs использует формат: где: prefix-normalizedname-hash

  • префикс — сокращение типа 3 букв (btn, txt, chk, cmb, itm, tab, img, lbl, pn, win, grp, lnk, mnu и т. д.)
  • нормализованное имя — буквенно-цифровые буквы нижнего регистра из AutomationId (предпочтительно) или name, максимум 15 символов
  • hash — хэш 4-char шестнадцатеричного хэша элемента RuntimeId (проверяет удостоверение элемента)

Slugs — это оболочкобезопасные (без специальных символов), уникальные и могут использоваться непосредственно в качестве аргументов. Без фильтров запросов хэш обеспечивает обнаружение устаревших данных— если элемент был заменен, вы получите сообщение "Элемент может измениться. Повторно выполните проверку". Сведения о отфильтрованных запросах см. в разделе "Область" и "Типизированные запросы".

Элементы без имени или AutomationId отображают только префикс + хэш (например, pn-c8a3).

Диамбигирование нескольких совпадений

Слизи из inspect/search выходных данных уникальны, но могут изменяться между изменениями макета. Используйте их над именами обычного типа или текстом при нескольких совпадениях. Если селектор неоднозначный, интерфейс командной строки печатает все совпадения со своими слизями, чтобы вы могли выбрать правильный и повторно запустить с этим слизь.

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, где Group, Button и Text все используют одно и то же имя), интерфейс командной строки автоматически выбирает единственный вызываемый элемент. Если несколько вызываются, он перечисляет все совпадения со слизями.

Для не вызываемых результатов поиска (например, 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

Commands

статус

Подключитесь к приложению и отображение сведений о подключении.

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

Проверить

Просмотр дерева элементов пользовательского интерфейса. Выходные данные показывают семантические семантические отступы с отступом в 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        # elements you can invoke, click, or set-value; 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="..." — текущее текстовое содержимое для редактируемых элементов (если отличается от имени)

Поиск элементов, соответствующих селектору. Выходные данные показывают семантические слизи:

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)

Slugs, отображаемые в выходных данных (например, 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
winapp ui get-property Document -p FontWeight -a myapp --json     # document formatting

Имена свойств чувствительны к регистру. Неизвестное имя завершается ошибкой invalid_arguments в разделе --json; опущено --property выводить список свойств, включая все шесть атрибутов форматирования текста ниже. wait-for --property использует те же имена с учетом регистра и отклоняет неизвестные имена перед опросом.

Форматирование текста в целом документе

Форматирование считывается по всему документу TextPattern элемента, а не по текущему выбору или уходу. Операции чтения не изменяют фокус или выделение.

Property Универсальное значение (возвращается в виде строки)
FontWeight Числовый вес, например "400" (обычный) или "700" (полужирный)
FontName Имя семейства шрифтов, например "Courier New"
FontSize Размер в точках, таких как "15.5"
ForegroundColor Десятичная Windows COLORREF (0x00BBGGRR), например "3678732" RGB(12, 34, 56)
IsItalic "True" или "False"
StrikethroughStyle Стиль оформления текста числовых элементов UIA, например "0" (нет) или "1" (один)

Числа используют инвариантное форматирование (десятичная точка независимо от языкового стандарта). Каждый атрибут может возвращать следующее:

Value Смысл и следующий шаг
"Mixed" Форматирование зависит от документа. Не рассматривайте его как однородное значение; Эта команда не запрашивает отдельные текстовые диапазоны.
"NotSupported" Поставщик TextPattern документа не сообщает об этом атрибуте. Проверьте поддержку специальных возможностей приложения.
"Unavailable" Элемент не имеет TextPattern. Используйте inspect или search найдите его текстовый или документный элемент.

При перечислении всех свойств кэшированные базовые свойства остаются доступными, если не удается разрешить динамический элемент, а неправильно сформированное значение форматирования опущено без отмены других свойств. Эти упущения регистрируются как предупреждения. Запросите определенное свойство форматирования, чтобы получить ошибку вместо упущения.

Ошибки поставщика остаются ошибками, а не "Unavailable". Для stale_elementэтого проверьте приложение снова и повторите попытку с помощью текущего селектора.

Конверт JSON содержит elementIdтипизированные elementи строковые propertiesзначения. Существующие свойства, в том числе BoundingRectangle, сохраняют их форматы. Например, часть properties форматирования:

{
  "FontWeight": "700"
}

снимок экрана

Захват окна или элемента в формате 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)

Без селектора элементов запись по умолчанию объединяет несколько окон в одну метку, параллельно составную PNG, а не отдельные файлы. -a по имени процесса или PID включает окна приложения и собственные окна. Совпадение на основе -a заголовка выбирает одно соответствующее окно и собственные окна; -w явно выбирает одно окно плюс собственные окна, а не каждое окно в процессе. Поэтому собственный диалог или подсказка может отображаться как собственная панель даже при явном выборе основного HWND. Селектор элементов обрезает этот элемент вместо создания окон. Элемент в меню, всплывающем элементе, подсказке или подсказке обучения, открывающемся в собственном всплывающем окне, обрезается из этого всплывающего окна, а не из окна за ним.

--quiet подавляет информационные выходные данные для одного окна и составных записей, включая сохраненный путь. Предупреждения и диагностика сбоев записи остаются видимыми. Используйте --json вместо этого, если требуется путь к файлу и измерения в качестве структурированных выходных данных.

С --on sandboxпомощью имени --output назначения узла. Успешные обычные выходные данные и --json отчет о том, что путь к узлу после доставки образа.

Путь записи по умолчанию использует Windows. Graphics.Capture (WGC), чтение фактической поверхности DWM с составной поверхностью — сохранение скругленными углами, прозрачностью и работой даже в то время как окно окклюзуется другими windows. Если ФУНКЦИЯ WPC недоступна (более старые Windows сборки) интерфейс командной строки возвращается в PrintWindow.

Используйте --capture-screen -w <hwnd> , если нужны видимые всплывающие окна или подсказки в их положениях на экране, включая наложения, которые не принадлежат целевому окну. Он считывает область экрана этого окна, а не создает помеченные панели и сначала переносит окно на передний план. Для -aэтого требуется ровно одно соответствующее окно; если совпадает несколько окон верхнего уровня или соответствующих окон, используйте winapp ui list-windows -a <app> и повторите попытку.-w <hwnd> Используйте --focus , если вы просто хотите переключить окно без переключения режимов захвата (например, чтобы убедиться, что снимок экрана соответствует текущему просмотру пользователя).

Так как контроллер домена экрана захватывает все, что на самом деле на самом деле, --capture-screenпроверяет целевой объект, достигнутый на переднем плане непосредственно перед захватом и завершается сбоем, foreground_not_target если он не (фокус-кража, запрос UAC или другое окно активации самого окна). Изображение не записывается в этом случае — ранее команда завершилась с 0 и вернула изображение неправильного окна. ui record --capture-screen Применяет ту же проверку перед первым кадром.

запись

Запишите область окна или элемента в H.264 MP4. Предпочитайте положительный результат --duration-sec для автоматических сценариев. Без длительности запись продолжается до ctrl+C или для перенаправленного stdin, newline или EOF. Npm uiRecord и targetRecord вспомогательные требуют целого числа durationSec от 1 до 86400; их сигнал прерывания отменяет принудительно, а не корректно завершить запись.

# 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

Варианты.

  • --duration-sec N — запись в течение N секунд. По умолчанию 0 записей до остановки.
  • --fps N — целевые кадры в секунду (по умолчанию 15).
  • --max-edge N — Уменьшение масштаба, поэтому самый длинный край составляет не более N пикселей (0 = без понижения).
  • --capture-screen — захват с экрана контроллера домена (включает наложения или всплывающие окна; передний план окна).
  • --output <path> — Путь к выходу MP4. По умолчанию — recording-<timestamp>-<guid>.mp4.
  • --overwrite — замените существующие выходные данные записи после завершения создания. Без него существующие выходные данные отклоняются.
  • --frames — запись метки времени в формате <output-name>.framesJPEG. Поддерживает 1-30 fps и --max-edge 64-4096 (по умолчанию 1280). Данные кадра ограничены 1 ГиБ; MP4 продолжается, если достигнуто ограничение.

Артефакты кадра, доступные для чтения агентом:

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

frames.ndjsonимеет одну строку на выборку с sampleIndexмонотоннымelapsedMs, MP4-относительнымmediaTimeMs, imageIndexи filechanged. Последовательные образцы, идентичные пикселям, повторно используют предыдущий формат JPEG-85.

manifest.json записывает запрос, время, состояние MP4, размеры изображения и состояние (complete, partialили truncated). Усеченное время охватывает сохраненный префикс, в то время как video описывает полный MP4.

Выберите новый выходной путь, если вы не планируете заменить запись --overwriteна . Без него либо существующее видео, либо его парный .frames каталог блокирует запись, даже если не указано --frames. Предыдущий MP4 остается неизменным, если новый захват завершается ошибкой. При успешной замене предыдущий каталог кадра сохраняется как <output-name>.frames.previous-<id>, даже если новая запись не используется --frames. Сохраните частичные доказательства и следуйте отчету recoveryHint перед повтором. Если завершение MP4 завершается ошибкой, сохраненные кадры можно опубликовать в разделе <output-name>.frames.partial-*. Артефакты кадра содержат незашифрованное содержимое экрана; обработайте их, как снимки экрана или видео.

При этом --on sandboxmp4 и каталог кадров доставляются на узел, включая выходные данные по умолчанию при --output опущении. См. запись песочницы для прерванных записей и записи всего рабочего стола.

Режимы записи (сообщается в поле JSON mode ):

  • wgc— Windows захват графики (по умолчанию; работает во время окклудирования окна).
  • printwindow — GDI PrintWindow (резервная обратная связь при недоступности WGC в этой системе или сеансе; повторно запустите его, --capture-screen чтобы использовать экранный контроллер домена).
  • screen — экранный контроллер домена --capture-screen через (включает наложения или всплывающие окна; выводит окно на передний план).

Выходные данные JSON (--json):

  • stdout: Окончательный результат записи, включая периодичность, причину остановки, необязательные frameArtifactsи предупреждения.
  • stderr: Один объект JSON на строку: recording-started событие после первого кадра, за которым следует ошибка при последующей записи. Пути кадров включаются только в том случае, если выходные данные кадра активны.

Коды ошибок:

  • element_not_found — Селектор не совпадал.
  • ambiguous_selector — селектор совпадает с несколькими элементами; используйте предлагаемый слизь.
  • invalid_arguments — недопустимое значение параметра.
  • output_exists — выходные данные записи уже существуют и не могут быть заменены в запрошенных параметрах.
  • frame_output_failed — После сбоя выходных данных кадра не может быть сохранен ни другой артефакт.
  • partial_output — завершено только один артефакт; проверка partialOutput и recoveryHint.

Селектор элементов записывает регион элемента из окна, в который он нарисован. Для элемента в меню, всплывающего меню, подсказки или подсказки обучения, открывающегося в своем окне всплывающего окна, запись показывает всплывающее окно, а не окно за ним.

Вызова

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 Open -w <dialog-HWND> --root Actions --type Button --class-name Button --action invoke
winapp ui invoke SubmitButton -a myapp

Используется --action , когда тест должен выполнять определенную операцию в выбранном элементе. Он никогда не пытается другой шаблон или вызываемый предок, даже если запрошенное действие завершается ошибкой. Элемент управления, поддерживающий вызов и выделение, будет выбран, а не вызван.--action select При использовании --actionslug предназначен ровно один элемент, а селектор простого текста или селектор AutomationId, соответствующий нескольким элементам, завершается сбоем без нуля, а не действует при первом совпадении, поэтому передайте слизь, когда inspect/search имя неоднозначно.

--root, --typeи сузьте совпадение, как описано в запросах с областью и типизированными запросами, с или без --actionнее.--class-name Используйте -w <dialog-HWND> для ограничения действия в этом диалоговом окне или -a <app> включения окон приложения. Отфильтрованный вызов подтверждает уникальный целевой объект перед действием, требует ровно одного соответствующего элемента и никогда не переключается на другое окно или вызываемый предок. Сбой нулевого совпадения с element_not_found; дубликаты завершаются ошибкой ambiguous_selector. Устаревший элемент или повторное окно завершается ошибкой, не выполняя действия; повторно запустите inspect или search выберите текущий селектор. Без --actionэтого отфильтрованный вызов по-прежнему пытается использовать шаблоны для одного элемента.

Action Operation
invoke InvokePattern.Invoke
select SelectionItemPattern.Select
toggle TogglePattern.Toggle, точно один раз
toggle-on / toggle-off Чтение ToggleState; Успешное выполнение без изменения уже правильного состояния, в противном случае переключение и проверка
expand / collapse ExpandCollapsePattern.Expand / Свернуть

Для toggle-on и toggle-off, начальное Indeterminate состояние разрешает не более двух переходов, проверяя состояние после каждого. Другие начальные состояния разрешают один переход. Если запрошенное состояние не достигнуто, команда завершается ошибкой, а не продолжается переключение. Сбой проверки может оставить элемент управления изменен; прочитайте ToggleState перед решением, что делать дальше.

Без --action фильтров автоматическое поведение без изменений: попробуйте invokePattern, TogglePattern, SelectionItemPattern, а затем ExpandCollapsePattern (развернуть) с повторным повтором вызываемого предка при необходимости.

Неподдерживаемое действие завершается ошибкой с кодом выхода без нуля и --jsonсо структурированной ошибкой на stderr. Проверьте выбранный элемент управления и выберите действие, поддерживающее его, или явно нацелив на предполагаемый родительский элемент. Json успешно включает requestedAction и performedAction; см. ссылку НА JSON.

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>с помощью, где каждая конечная точка — это селектор элементов (перетаскивает из центра элемента) или координаты x,yэкрана точно так же, как сообщаетсяwinapp ui inspect. Смешивайте и сопоставляйте свободно (селектор→селектор, селектор→coords, coords→coords).

Используется SendInput с промежуточными перемещениями, поэтому приложение видит реалистичный поток WM_MOUSEMOVE сообщений. Используйте его для переупорядочения или изменения размера дескрипторов, ползунка, рисования холста и перетаскивания.

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). Позволяет удалять целевые объекты или наложения слиянием , которые выполняются на основе устойчивого наведения указателя мыши (а не мгновенного поступления курсора) перед нажатием кнопки.

Голые x,y — это координаты экрана в одном и том же отчете о пространстве winapp ui inspect/search , а селектор разрешается в центр элемента — сначала проверьте точки.

Например send-keys --via send-input, drag внедряет ОС на экранные координаты после ввода целевого объекта на передний план. Если фокус не может быть доставлен в целевой объект (например, предотвращение кражи фокуса из фонового процесса), команда завершается ошибкой (foreground_not_target), а не перетаскиванием неправильного окна — фокус или щелкните окно первым. На заблокированном или безопасном рабочем столе происходит сбоем no_interactive_desktop. Каждая конечная точка элемента повторно разрешается сразу перед перетаскиванием; Если он по-прежнему перемещается или изменяет размер (анимирующий целевой объект), команда завершается сбоем target_moved вместо перетаскивания в устаревшую точку. (Не удается повторно проверить конечные точки, x,y поэтому они используются as-is.)

трогать

Внедрение искусственных жестов касания с помощью API внедрения указателя Windows указателя. Привязка контакта — это селектор элементов (использует центр элемента) или явную координату x,yэкрана через --at (те же отчеты о пространствеwinapp ui inspect). Используйте его для взаимодействия касания и нажатия клавиш и много сенсорных жестов, которые имитация мыши не может выразить.

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-pressswipe, pinch, stretch.
  • --at <x,y> — явная начальная точка (координаты экрана). По умолчанию используется центр элементов селектора.
  • --to-point <x,y> — конечная swipeточка для . Имеет приоритет над --direction.
  • --direction <right|left|up|down> — направление прокрутки (по умолчанию: right). В сочетании с --distance вычислением конечной точки, когда --to-point она не указана.
  • --distance <px> — палец распространяется на расстояние в pinch/stretchпикселях или проводите пальцем в пикселях.
  • --hold-ms <ms> — удерживайте контакты вниз до отмены (время удержания длительного нажатия; по умолчанию — 500 мс, если long-press не задано).
  • --duration-ms <ms> — время перемещения жестов (проводите пальцем или растяжением; по умолчанию — 300).
  • --fingers <n> — число контактов (1–10; по умолчанию 1). pinch / stretch всегда используйте 2.

Безопасность инъекций. touch отказывается внедряться, если ненулевой целевой дескриптор окна не разрешается, и это окно содержит передний план — он завершается ошибкой, no_target если не удается разрешить окно, foreground_not_target если фокус не удалось передать или на заблокированном или no_interactive_desktop безопасном рабочем столе. Каждая координата (центр элементов, явные и созданные точки пути) --at; точка за пределами окна отображается как неустранимое /--to-pointпредупреждение (warnings[]запись в --jsonтекстовом режиме или строка предупреждения в текстовом режиме) и внедрение по-прежнему продолжается — соответствует командам мыши (click/drag/hover/scroll), которые также внедряются в координаты вне окна. --fingers выше 10 отклоняется вперед.

Заметка о оборудовании. Сенсорный интерфейс предпочитает современное устройство с искусственным указателем (CreateSyntheticPointerDevice(PT_TOUCH)) и возвращается к устаревшей InitializeTouchInjection/InjectTouchInput API. Если внедрение не поддерживается на текущем устройстве или сеансе, команда обнаружает фактический код ошибки Win32 (например, "неподдерживаемый"), а не сообщает о ложном успешном выполнении— обработает ненулевое завершение как "касание не доставлено".

Remote Desktop / сеансы виртуальной машины. В Remote Desktop (RDP) или некоторых сеансах виртуальной машины ОС может принимать искусственный сенсорный касание (выход 0) без фактического достижения целевого приложения. При обнаружении touch удаленного сеанса добавляет предупреждение о неопределенности доставки — warnings[] запись --jsonв или строку предупреждения в текстовом режиме. Значение ✅/exit 0 означает, что вызов внедрения выполнен успешно, а не то, что приложение получило входные данные; подтвердите эффект с ui screenshot/ui inspect тем, когда это важно.

ручка

Внедрение искусственных пера и пера пера и пера ввода — касания и росчерки рукописного ввода — с помощью API Windows искусственного указателя (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 ввода как пары пробелов (одноточечный путь — это касание).
  • --pressure <0.0–1.0> — давление пера (по умолчанию 0,5).
  • --tilt-x <deg> / --tilt-y <deg> — угол наклона пера, –90–90 (по умолчанию — 0).
  • --eraser — используйте конец ластика пера вместо чаевых.
  • --duration-ms <ms> — Общее время перемещения штрихов в миллисекундах, распределенных как интерполированные кадры UPDATE по пути (по умолчанию: ~10 мс на точку пути). Используйте это для управления тем, как быстро перо заметно перемещается от начала к концу.

Безопасность инъекций. Как touchи , pen отказывается внедрять без нуля, переднего плана целевого окна () и no_target на прямоугольник целевого окна, отображая любую внеоружную координату как неустранимое / (foreground_not_target / no_interactive_desktopwarnings[]в --jsonили строке предупреждения в текстовом режиме) во время внедрения — в соответствии с командами мыши. Недопустимые --pressure (за пределами 0.0–1.0) или наклон (вне ±90°) отклоняются вперед.

Remote Desktop / сеансы виртуальной машины. Маршрутизация пера особенно ненадежна по сравнению с Remote Desktop: вызов внедрения может сообщать об успешном выполнении (выход 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 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

Варианты.

  • --dwell-time <ms> — время в миллисекундах, чтобы подождать после наведения курсора на эффекты (по умолчанию: 800, диапазон: 0–10000)

send-keys

Отправка искусственных входных данных с помощью клавиатуры — в . UIA не имеет шаблона внедрения клавиатуры, поэтому это удаляется на слой Win32. Используйте его для навигации по клавиатуре (стрелки, вкладка, ВВОД, 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
winapp ui send-keys "ctrl+capslock+f12" -a myapp --via send-input  # Narrator command: toggle developer mode

Грамматика ключа (маркеры, разделенные пробелами, кавычки строк с несколькими токенами):

  • Именованные ключи — enter/return, tab— esc/escapespacebackspacedelete/delinserthomeendpageup/pguppagedown/pgdnup/down/left/rightf1f16appsprintscreencapslock
  • Последовательности — несколько маркеров нажимаются в порядке: down down enter
  • Модификатор со списком — ctrl, shiftalt, win присоединенный к +: ctrl+shift+t, alt+f4. Маркер, который начинается с модификатора, но имеет неизвестный сегмент до последней (ctrl+a+b) является ошибкой; используйте text= или --verbatim введите его.
  • Команды средства чтения с экрана — удержание capslock или insert (псевдоним ins), экранный диктор, NVDA и клавиша JAWS: ctrl+capslock+f12 переключение режима разработчика экранного диктора. Требуется --via send-input, так как средства чтения с экрана не получают опубликованные ключи. Если средство чтения с экрана не запущено, удерживая capslock клавиши Caps Lock или off, и команда предупреждает, чтобы insert избежать этого.
  • Литеральный текст — любой маркер, который не является известным ключом, введите символ по символу: hello Смежные литеральные слова сохраняют пространство между ними, поэтому кавычки, как и типизированные фразы, как "Hello world" типизированные (пробел сохраняется); литерал, который просто содержит + , например C++ или a+b типизированный как текст, а не синтаксический анализ как комбо.
  • Явный escape-литерал — префикс маркера с text= типом его детализации даже при столкновении с именем ключа или модификатора: text=enter введите слово ввод вместо нажатия клавиши ВВОД и text=ctrl+a введите литеральную строку. Зеркально экранирование; экранированное vk= значение по-прежнему объединяется со смежными литеральными словами (text=down low → "вниз низко"). Так как маркеры разделены пробелами (и смежные литералы повторно присоединяются с одним пробелом), используйте обратную косую косую черту внутри text= значения , чтобы ввести пробелы, которые не будут выжить в противном случае: \s → пробел \t , → вкладка, \n → newline, → newline, \r\\ → литерал обратной косой черты. \n, \rи \r\n каждая вставка одного разрыва строки (ввод/ VK_RETURN), поэтому text=line1\nline2text=line1\r\nline2 оба типа введите одну новую строку. Таким образом, text=a\s\sb введите "a b" (двойное пространство) и text=\shi сохраняет ведущее пространство. Нераспознанный escape (например \x, ) остается подробным.
  • Литерал целого аргумента (--verbatim) — когда весь полезный текст является литеральным текстом, передайте --verbatim вместо того, чтобы экранирование каждого токена с text=помощью. Он вводит весь аргумент ключей точно так же, как указано — без именованного ключа/combo/vk=/text= интерпретации— и, в отличие от обычного пути, сохраняет точное внутреннее пространство пробелов (без сворачивания) без необходимости.\s Поэтому send-keys "down down enter" --verbatim вводит слова и send-keys "a b" --verbatim сохраняет двойное пространство. Триггеры обратной косой черты не декодируются в режиме (--verbatimтипизированный как \s обратная косая черта и "s"); используйте text= маркер, если вам нужен экранированный символ элемента управления.
  • Необработанные виртуальные ключи — vk=0xNN (шестнадцатеричное) или vk=NN (десятичное) для ключей без понятного имени.

Варианты.

  • --target <selector> — фокусировать этот элемент (через UIA) перед отправкой ключей. Без этого ключи переходят к текущему элементу приложения.
  • --verbatim — Введите весь аргумент ключей в виде литерального текста (без ключа/combo/vk=/text= синтаксического анализа) и сохраните точное пространство пробелов. Форма полного аргумента для escape-маркера text= .
  • --via <transport>— post-message (по умолчанию) записиWM_KEYDOWN/WM_KEYUP/WM_CHARв очередь целевого окна. Он предназначен для HWND и проходит UIPI (работает на разных уровнях целостности). send-input внедряет операционную систему через SendInput окно переднего плана и переходит в окно переднего плана.

Выбор транспорта / известных ограничений:

  • post-message — это значение по умолчанию, так как оно проходит UIPI и не зависит от окна переднего плана. Ограничения: он не может активировать глобальные горячие ключи, зарегистрированные через WH_KEYBOARD_LL низкоуровневые перехватчики (те, которые касаются входящего выше потока любой очереди окна), и приложения, которые считывают состояние необработанного ключа с помощью GetAsyncKeyState не наблюдаемых модификаторов. Он автоматически разрешается и публикуется в дочернем окне целевого потока (через GetGUIThreadInfo) после переднего плана, поэтому классические приложения Win32/WinForms, элементы управления которых являются отдельными дочерними окнами, не нацеливаясь на элемент управления вручную. Приложения WinUI 3 / UWP имеют элементы управления XAML без дочернего HWND, поэтому размещенное WM_CHAR/WM_KEYDOWN не имеет ничего, чтобы приземлиться и удаляется, — после сообщения не удается управлять ими (команда предупреждает и выходит из 0); используйте.--via send-input (WPF окна являются одним HWND и ключами маршрута к внутреннему элементу, поэтому после сообщения работает там.)
  • send-inputсоздает полностью реальные входные данные (модификаторы, видимые GetAsyncKeyStateдля , запускает низкоуровневые перехватчики), но переходит в любое окно переднего плана и блокируется UIPI при внедрении из повышенного процесса в целевой объект с более низкой целостностью (AppContainer/AppX). Если send-input сообщает о сбое, целевой объект, скорее всего, повышен или приложение AppX — используйте post-messageили запустите ИНТЕРФЕЙС командной строки на соответствующем уровне целостности. Как охранник безопасности проверяет, send-input что целевое окно на самом деле находится на переднем плане непосредственно перед внедрением и сбоем (foreground_not_target), а не ввод в неправильное окно , если фокус не удалось привести к нему — фокус или щелкните окно первым. На заблокированном или безопасном рабочем столе вместо этого не удается no_interactive_desktop (нет окна переднего плана для внедрения) — разблокируйте сеанс или используйте команду UIA-pattern (set-value, ). invoke
  • Системные зарезервированные combos (win+l, win+rctrl+shift+escctrl+alt+delalt+tabalt+f4ctrl+esclonewin/printscreen, ...) действуют на ОС или оболочке, а не только на целевом объекте при отправке ос на уровне ОС. send-input отклоняет их по умолчанию (ошибки с invalid_arguments и не отправляет ничего), так как внедрение их на уровне ОС влияет далеко за пределы целевого окна (например win+l , блокировка сеанса). Передайте --allow-system-keys , чтобы принять участие — это позволяет управлять глобальным горячим ключом, например PowerToys' win+shift+v или win+r (глобальный низкоуровневый перехватчик наблюдает за потоком ввода на уровне ОС, поэтому внедренный комбо запускает его). Исключения, которые остаются заблокированными даже с --allow-system-keysпомощью :win+l блокирует рабочую станцию, с помощью LockWorkStation() которой не удается получить доступ к автоматизации (разрывает сеансы CI и удаленных рабочих столов) и ctrl+alt+del является последовательностью безопасного внимания (SAS), которая Windows удаляется из внедренных входных данных независимо от флага , поэтому она никогда не может входить в силу, поэтому она не может входить в силу (invalid_argumentsвыход 1), а не сообщать об ошибке в заблуждение. Другие combos (alt+f4, , ctrl+shift+escwin+r...) становятся разрешенными с флагом — вызывающий остерегайтесь. Кроме того, для доставки системного combo в определенное окно используется--via post-message, что является областью действия окна и не влияет (размещено безвредно, хотя размещенное win+lalt+f4 по-прежнему закрывает целевое окно).

События ввода ключей (KeyDown / TextChanged):

  • Именованные ключи и модификаторы со списком (down, , enter, ctrl+shift+tvk=0xNN) запускают реальный KeyDown (иKeyUp) на обоих транспортах — они доставляются как дискретные WM_KEYDOWN/WM_KEYUP (или SendInput события виртуального ключа).
  • Текстовый типизированный текст (hello) отличается от транспорта:
    • --via send-input сопоставляет каждый символ с его виртуальным ключом (плюс shift) на активном макете клавиатуры, поэтому целевой объект видит подлинный KeyDown с правильным виртуальным ключом , за которым следует ОС,состоящий WM_CHAR (повышение TextChanged) — т. е. один полный нажатие клавиш на символ. Символы, недоступные в текущем макете (или требуя CTRL/ALTGr), возвращаются к пакету Юникода, чтобы точный символ по-прежнему приземляется. Используйте, когда требуется send-input точность нажатия KeyDown клавиш (например, вождение WinUI 3/WPFTextBox, обработчики которого отключеныKeyDown). Для обычного тестового узла WinUI 3 (без повышенных привилегий) сначала доведите окно на передний план (winapp ui focus /щелчок) после того, как send-input оно предназначено для окна переднего плана.
    • --via post-message публикует один символ WM_CHAR (он не публикует WM_KEYDOWN/WM_KEYUP типизированный текст — они зарезервированы для именованных ключей и combos), что не создает символ для каждого символа KeyDown. Он автоматически перенацеливается на ориентированный дочерний элемент управления окна, поэтому классический элемент управления "Win32/WinForms WM_CHAR", управляемый изменениями, помещает текст (повышение TextChanged). Предостережение: Приложения WinUI 3 / UWP / XAML (основной целевой объект winapp) имеют элементы управления без окон , которые игнорируют опубликованные WM_CHAR/WM_KEYDOWN элементы управления, поэтому ни литеральный текст, ни именованные ключи (ВВОД, цифры, ...) не достигают их, даже если команда сообщает об успешном выполнении команды. Он выдает предупреждение, когда целевой объект выглядит как XAML и по-прежнему выходит из 0 (PostMessage является пожаром и забыть и не может подтвердить доставку). Используется --via send-input для диска WinUI 3 / UWP / WPF приложений; резервируете post-message для классических элементов управления Win32 или если требуется только область окна на уровне целостности.

Выходные данные JSON (--json): результатом hwnd является эффективное окно, в котором были доставлены ключи. Для --via post-message этого разрешенный дочерний элемент управления, когда команда перенацеливает его (не обязательно окно верхнего уровня-w/-a/-e), поэтому автоматизация может подтвердить, где приземлились входные данные. Если этот действующий целевой объект выглядит как узел XAML без окна, указанный выше, также отображается warnings[] как запись (те же рекомендации, что и на консоли), поэтому ✅ выход 0 не ошибается для подтвержденной доставки.

set-value

Задайте значение для редактируемого элемента программным способом (без нажатий клавиш, без переднего плана приложения). Использует резервную цепочку:

  1. ValuePattern — TextBox, ComboBox, PasswordBox и большинство редактируемых элементов управления.
  2. RangeValuePattern — числовые элементы управления (Ползунок, ProgressBar), когда значение анализируется как число.
  3. LegacyIAccessible (IAccessible::put_accValue) — резервный вариант для элементов управления редактированием только для TextPattern , которые не предоставляют значения ValuePattern (например, форматированные поля и Document поля создания). Это закрывает разрыв чтения и записи, где get-value может прочитать такой элемент управления, но set-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 3 RichEditBox и WPF RichTextBox не поддерживают программную настройку значений. При проектировании они предоставляют содержимое модель автоматизации пользовательского интерфейса как доступные только для чтения (текстовый шаблон, шаблон значений не задан), поэтому 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 get-value SearchBox -a myapp --json
winapp ui wait-for SearchBox -a myapp --value "" --timeout 5000

Пустое текстовое поле успешно считывается "text": "", а не метка специальных возможностей. Содержимое только для пробелов также сохраняется в ФОРМАТЕ JSON. wait-for --value "" соответствует пустому полю, независимо от того, является ли он свежим или был очищен после редактирования. Для чтения метки специальных возможностей используйте get-property --property Name.

концентрация

winapp ui focus txt-textbox-a4b1 -a notepad

Активирует окно выбранного элемента управления при необходимости, а затем фокусирует элемент управления. Селектор является обязательным; используйте -a <app> или -w <HWND> выберите целевой объект. Успешное выполнение означает, что окно было передним планом и выбранным элементом управления, подтвержденным HasKeyboardFocus до возврата команды. Команда позволяет управлять фокусом до 500 мс; он останавливается, если целевой объект исчезает или теряет передний план, а не пытается вернуть фокус назад. Диалоговое окно, принадлежащее главному окну, недостаточно: выберите элемент управления в диалоговом окне, если это ваш целевой объект.

Эта команда нуждается в разблокировке, интерактивном рабочем столе и не пропускает ограничения активации Windows. Если он завершается ошибкой foreground_not_target, вручную активируйте предполагаемое окно и проверьте наличие диалогового окна блокировки перед повтором. Для focus_not_acquiredэтого проверьте текущий пользовательский интерфейс и выберите фокусируемый элемент управления. Для stale_element, повторное обнаружение целевого объекта с inspect помощью или search. Сохраняйте тот же --on целевой объект при обнаружении и повторных командах.

прокрутка в представление

Прокрутите элемент в видимой области.

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

ожидание

Подождите, пока элемент появится, исчезнет или имеет значение, достигающее целевого объекта.

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> — синтезирование ввода мыши в центре элемента через SendInputколесики (детенты): 1 = один зарез вверх/вдали, -1 = один зарез вниз/в сторону, 3 = три зачески вверх. (Каждая ноча — это Windows WHEEL_DELTA из 120 единиц, которые SendInput используются; интерфейс командной строки масштабируется на 120 единиц. ОбходыScrollPattern.

--direction, --toи --wheel являются взаимоисключающими — проходят ровно один. Так как --wheel внедряет входные данные на уровне ОС в координатах экрана, он приводит целевой объект к переднему плану в первую очередь и завершается ошибкой (foreground_not_targetесли фокус не удалось передать, а не прокрутит неправильное окно.

получение фокуса

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

Отображение элемента, который в настоящее время имеет фокус клавиатуры в выбранном приложении, включая элементы управления, права владения приложениями доступны только через родительское окно. При этом -wфокус должен принадлежать к окну, а не другому окну или всплывающему окну в том же процессе. При -aэтом включены другие окна выбранного процесса. Выходные данные JSON имеют, hasFocus:false если не может быть проверен элемент с фокусом как принадлежащий целевому объекту. Если запрос фокуса или права владения окном завершается сбоем, команда завершается ненулевой; Повторите get-focusedпопытку и повторно обнаружите окно, list-windows если оно закрыто.

List-windows

Вывод списка всех видимых окон для приложения, включая всплывающие окна и диалоговые окна. По умолчанию неинициализированные окна с нулевым размером (невидимыми системными окнами) исключаются.

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

доходность

Выпустите пользовательский интерфейс этого рабочего процесса рано, а не ожидая четверо-секундной бездействия. Требуется WINAPP_UI_WORKFLOW_ID; не принимает приложения и ни селектора. См. статью о начале выпуска.

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

Поддержка платформы

Платформа Проверить search Вызова set-value снимок экрана
WPF ✅ Полное дерево ✅ Все свойства ✅ Все шаблоны ✅ ¹ ✅
WinForms ✅ ✅ ✅ ✅ ✅
Вин32 ✅ ✅ ✅ ✅ ✅
WinUI 3 ✅ ✅ ✅ ✅ ¹ ✅
Электрон ⚠️ Дерево Chromium ⚠️ Ограничено ⚠️ Зависит ⚠️ Зависит ✅
Flutter ⚠️ Базовый ⚠️ Базовый ❌ Минимальный ❌ ✅

¹ set-value работает над любым элементом управления, предоставляющим значение ValuePattern/RangeValuePattern, а также элементы управления редактирования только TextPattern, специальные возможности которых реализуются IAccessible::put_accValue (резервная версия LegacyIAccessible). WinUI 3 RichEditBox и WPF RichTextBox являются исключениями— они предоставляют только шаблон текста только для чтения (без шаблона заданного значения), поэтому они не могут быть заданы программным способом. Используйте send-keys (требуется интерактивный рабочий стол) для ввода в них.

Использование подсистемы из собственного кода

Все winapp ui это доступно в виде библиотеки, поэтому вы можете использовать ту же автоматизацию из тестового или средства без оболочки в ИНТЕРФЕЙС командной строки:

Package Что это добавляет
Microsoft.Windows.SDK.BuildTools.WinApp.UIAutomation Проверка, селекторы, взаимодействие шаблонов UIA, внедрение входных данных, снимки экрана
Microsoft.Windows.SDK.BuildTools.WinApp.UIAutomation.Recording Запись видео в MP4, а также пакеты кадров
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);

Для детерминированных действий используйте перегрузку 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 отклоняет неоднозначный текст вместо выбора вызываемого совпадения. Точные совпадения AutomationId имеют приоритет над именами или подстроками AutomationId; Уникальное имя по-прежнему может выбрать элемент управления, общий доступ к которому предоставляется AutomationId. Для целевого объекта с областью действия приложения проверка охватывает все его окна или окна, принадлежащие приложению. Используйте -w <HWND> (или целевой объект библиотеки явного окна) для ограничения области выбора.

Он возвращает Pattern и с теми же значениями, что и PerformedActionрезультат действия CLI. Передайте элемент, возвращаемый проверкой или выделением, со своими фрагментами среды выполнения или уникальными идентификаторами AutomationId без изменений. Явные действия отклоняют отсутствующие или неоднозначные удостоверения, а не перевязывание по имени и типу элемента управления.

Для операций чтения в области задайте UiSelector.Root для другого UiSelectorтипа ControlType имя типа и ClassName класс поставщика литерала. Они используют те же предикаты запросов , что и интерфейс командной строки. Поддерживается только один корневой уровень: selector.Root.Root должен быть null. Вложенный корень вызывается ArgumentException перед поиском целевого окна. Вместо вложенных корневых селекторов используйте уникальный корневой код AutomationId или slug. UiControlTypes.GetId(name) разрешает официальные имена типов и два задокументированных псевдонима, возвращая 0 недопустимое имя. UiControlTypes.GetName(id) возвращает каноническое имя или Unknown(id) для нераспознанного идентификатора.

При передаче восстановленного UiElement из JSON GetTextAsync в или GetPropertiesAsyncсохраните его Selector и WindowHandle. Селектор slug должен по-прежнему определять исходный элемент; Если он больше не существует, эти операции считываются UiElementNotFoundException вместо выбора другого элемента с тем же именем AutomationId или name. Запустите исходный запрос еще раз, чтобы обновить результат. Область чтения также распространяет сбои от общих методов получения свойств UIA и полученных шаблонов UIA, а не возвращая значение NULL или ранее захваченное значение.

Запись — это отдельный пакет, чтобы проекты, которые только проверяли и не извлекли пользовательский интерфейс диска в SkiaSharp. Пакет автоматизации предназначен net10.0-windows для обоих целей net10.0-windows10.0.19041.0и; последний добавляет Windows графическую запись, что позволяет screenshot записывать occluded или gpu составные windows. Ознакомьтесь с readME каждого пакета в NuGet для полного API и компромисса целевой платформы.

UiTarget.FromWindowHandle — это точка входа для тестовых платформ, которые уже перенаправляют окно, например MSTest.Windows.UIAutomation, чья WindowTest.MainWindow платформа UIA2 AutomationElement выполняет мост с MainWindow.Current.NativeWindowHandleпомощью .

Troubleshooting

Error Причина Решение
"Не найдено работающего приложения" Несоответствие имени приложения или не выполняется Проверка имени процесса или использование PID
"Совпадение с несколькими окнами" Неоднозначное -a значение Использование -w <HWND> из перечисленных параметров
"имеет несколько окон" Процесс содержит несколько окон Использование -w <HWND> для целевой конкретной.
"Селектор совпадает с элементами N" Неоднозначный селектор прежних версий Использование slugs из inspect выходных данных или добавления [0]к [1] устаревшим селекторам
"Элемент, возможно, изменился" Хэш slug не соответствует текущему элементу Повторное выполнение inspect или search получение свежих слизей
"не поддерживает какой-либо шаблон вызова" Не удается вызвать элемент Использование inspect элемента для поиска вызываемого дочернего элемента
"Окно UIA не найдено" UIA не может видеть процесс Используйте list-windows для поиска HWND, а затем -w
"Окно имеет нулевой размер" Окно свернуто Приложение будет автоматически восстановлено
Всплывающее окно или раскрывающееся меню не на снимке экрана Запись по умолчанию выполняется в каждом окне и не включает неуправляемые наложения Выполните рабочий процесс наложения снимок экрана , чтобы выбрать окно с помощью -w <hwnd> --capture-screen
foreground_not_target из --capture-screen Windows отказался от активации, поэтому запись с экрана будет записывать любое окно на самом деле перед Щелкните целевое окно или закройте окно кражи фокуса и повторите попытку или удалите --capture-screen
element_not_found во время записи Селектор, заданный, но не соответствует элементу Повторное выполнение inspect или search получение нового селектора
РАБОЧАЯ группа недоступна во время записи Сбой записи в формате WPC; безмолвный резервный вариант Проверьте GPU или драйвер; использование --capture-screen для предоставления согласия на запись с экрана-DC

Общие шаблоны

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

Обнаружение, щелчки и проверка

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

Диалоговое окно "Файл"

Диалоговые окна открытия и сохранения файлов — это стандартные диалоговые окна Windows с поддержкой 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>

Используется inspect -w <dialog-hwnd> --interactive для обнаружения фактических слизей для определенного диалогового окна.

Почему ; для цепочки (не &&)

Оператор PowerShell && может заморозить, когда собственный интерфейс командной строки записывает в stderr или использует escape-последовательности ANSI. Используйте ; вместо этого — он выполняет каждую команду без каких-то условий и избегает этой взаимоблокировки. Это также лучше для рабочих процессов агента: обычно требуется запустить снимок экрана, даже если вызов ненулевым выходом.

Шаблоны тестирования CI

Используйте команды winapp ui в конвейерах CI (GitHub Actions, Azure DevOps) для тестов дыма и проверки пользовательского интерфейса. 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

Состояние элемента Assert с wait-for

wait-for --value опросы до тех пор, пока значение элемента не соответствует ожидаемой строке, используя ту же интеллектуальную резервную строку, что get-value и (TextPattern → ValuePattern → SelectionPattern → Name). Возвращает код выхода 0 в совпадении, код выхода 1 во время ожидания— что делает его понятным утверждением CI. Используйте --property для проверки определенного свойства UIA.

# 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

Используйте --json PowerShell или jq для более сложных утверждений:

Контракт exit-code для 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)" }

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

Конверты JSON:

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

Типизированные элементы используют type и числовые x, ywidthи height. Геометрия находится в физических пикселях экрана. 0,0,0,0— это пустой прямоугольник пользовательского интерфейса модель автоматизации пользовательского интерфейса без отображения в этой проекции, поэтому isOffscreen элемент вне экрана по-прежнему может иметь ненулевые границы.

Каждая inspect --jsonwindows[] запись и status --json результат включают windowDpi, scale (windowDpi / 96), dpiAwarenessи coordinateSpace: "physical-screen-pixels". Они описывают контекст DPI целевого окна, а не безусловный DPI монитора: Windows сообщает 96 для неузнаваемого окна, системного DPI для окна с поддержкой системы и текущего DPI монитора для окна с учетом монитора. Если не удается прочитать контекст HWND или DPI, команда завершается ошибкой, а не автоматически подставляя 96. При status разрешении процесса до его появления окна верхнего уровня поля DPI будут пропущены до тех пор, hwnd0 пока окно не существует. Для всего inspectпроцесса выбранное целевое окно остается неудачным. Если после чтения дерева появится более поздняя всплывающее окно, то его windows[] запись содержит dpiError поля DPI и исключает поля DPI, а остальные деревья окон по-прежнему возвращаются.

Полные примеры каждого конверта см. в winapp-ui-automation предоставленных навыках references/ui-json-envelope.md .

Полный пример теста дыма

# 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