Skip to main content

Which Windows applications SPART-Desk covers, and how well

Windows applications are built with many toolkits, and each tells UI Automation a different amount about itself. This page rates, per kind of application, how much of it SPART-Desk can test today, what stands in the way, and what would lift it. It is kept current as toolkits are verified.

Ratings​

RatingMeaning
FullSemantic locators, state (checked, expanded, enabled, value), and actions through UI Automation patterns that work in a background window.
GoodThe accessibility tree carries it; some controls need reading the screen or real input in the foreground.
PartialThe window frame and standard controls come from the tree; the content only through reading the screen and clicks in the foreground.
PixelsReading the screen and clicking at coordinates only; the window in the foreground; no state.
BlockedRefused, or impossible today.
EvidenceMeaning
TestOne of SPART-Desk's own tests drives such an application.
ManualChecked by hand.
ExpectedWhat the toolkit is known to expose; not verified here.

The matrix​

What each feature does on each kind of application, case by case, is in the feature-by-application matrix: every case of the shared contract (a form, a tree, a list, a modal dialog, the window, the input devices, the clipboard, and with --more radio buttons, a slider, a spin box, tabs, menus, a context menu, double clicks, hovers and tooltips, drags, keys and a grid) on each of 22 kinds of application (27 columns: five are a second build or runtime of the same application), rendered from SPART-Desk's own contract runs. Each limit there carries its sentence. A limit is something the application does not give, and SPART-Desk says so when asked: a refusal within a second or two, or a Why: line when a wait ends. A silent case would be one SPART-Desk cannot tell: the application reports a wrong state, or ignores what it is sent. No case is a gap on any kind of application, and none is silent: every case that applies passes or is a limit SPART-Desk says, and the matrix's summary table has the counts per application. The table below rates each kind of application as a whole.

Kind of applicationExamplesTodayEvidenceWhat stands in the wayWhat would lift it
Win32, MFC, common controlsCharacter Map, classic dialogs, MFC applicationsFullTest (a #32770 dialog of common controls, the window's menu and the common dialogs, with another window in front; System Information, an MFC application of Windows; charmap; win32-apps.md)State and actions the tree lacks go through the controls' own windows: radio buttons, trackbar, date picker, SysLink, up-down, the window's menu (read, not shown), its shortcuts, context menus, clicks and double clicks posted to a window behind another. List views are read through their messages (10,000 rows in under a second), and a window beside a big one through the helper's own tree. Owner-drawn items without text are named from the screen. A chord no menu lists is posted with its modifiers held; a list view's item is double- or right-clicked on its text, behind another window too; a control the application paints itself (charmap's grid) is read off the screen, behind another window too, and clicked with its window in front. Hover needs the foreground, and so does focus() where the window is not its thread's active window. RichEdit 2.0/3.0 fields (riched20.dll, as MFC's CRichEditCtrl, older Delphi TRichEdit and VB6 make them) pass the shared contract, Unicode and ANSI; an ANSI one holds only its code page's characters.—
Scintilla editorsNotepad++, SciTE, TortoiseGit and TortoiseSVN commit dialogs, Code::BlocksFull (the editor)Test (Notepad++ 8.9.8.1 and SciTE 5.6.7, behind another window)UI Automation reports the editor as a pane named with its whole text and no pattern: it is a text box whose value is that text, read through its window, filled and typed into through its window in the background (line ends as the Enter key, the application's auto-indent undone). Notepad++'s menu, tabs, status bar and Find dialog are Windows' own; its toolbar buttons have no names. Hosts other than Notepad++ unverified—
Windows Formsline-of-business applicationsFullTest, on the .NET Framework 4.8 and on .NET 10 (the standard controls and a 5,000-row grid with another window in front; dotnet-apps.md)Grids are read through the helper's MSAA reader: ~1 s for 500 rows, ~5–8 s for 5,000 (~4.5 s on .NET 10, whose rows not shown have no place and whose row names are slow to ask); the rest of a window beside a big grid through the helper's own tree, ~1–2 s a locator. A ToolStrip check button's state is read through MSAA, a NumericUpDown's arrows step it through its edit, a ContextMenuStrip's item is chosen and a menu strip's shortcut pressed in the background. Third-party suites that paint their controls are covered on Krypton: a field painted around Windows' own control is that control, a painted button or check box is read off its pane's picture and clicked with real input, and the ribbon's tabs and buttons by their painted text; a painted navigator's page header is told chosen by the page read inside it (DevExpress, Telerik and Infragistics themselves unverified). Also: MDI documents as windows inside their container; a MenuStrip's window list once opened; a NotifyIcon's menu through desktop.shell(); a window recreated with a new handle; a PropertyGrid, a MonthCalendar, autocomplete, a SplitContainer and a scrolling panel. On .NET 8+ a CheckOnClick ToolStrip button is a check box, a PropertyGrid's properties are tree items, and FolderBrowserDialog is the file dialog's folder mode (dotnet-apps.md). A DateTimePicker's days are read off the screen, a ToolStripSplitButton's menu opens by a click posted on its arrow (its pattern would run its command), and a shell autocomplete list takes a choice only from the real mouse.—
WPFline-of-business applicationsFullTest (dotnet-apps.md)Virtualised lists hold only the rows on screen: a row of a grid in order by the column asked for is reached by setting the grid's scroll position to where it should be (row 7,842 of 10,000 by its Id in about 5 s, selectOption of item 150 of 10,000 in about 5 s); rows in no order by it are paged to a view at a time, the grid looked at alone between pages (a row 150 down, found by two of its cells, in about 23 s); WPF may bring its window forward when paged or focused through UI Automation. In-house controls: labels in another panel, template text (read from the Raw view), tables of plain text, and charts, forms and whole windows that paint their content (tables, input boxes and buttons found in the picture) are handled; real input to what is only painted needs the foreground. A WPF ribbon's tabs, group buttons, toggle and application menu are driven; its RibbonComboBox, a menu bar to UI Automation, is reported as the combo box it is and driven by selectOption. Re-templated WPF controls (Material Design In XAML) keep their automation peers, and a Fluent.Ribbon's tabs, group buttons and combo box report their roles. A WPF form hosted in Windows Forms (ElementHost) and a Windows Forms form hosted in WPF (WindowsFormsHost) read as one tree across the seam—
WinUI 3, Windows App SDK, .NET MAUIWindows 11 Notepad, Terminal, PaintFullTest (an unpackaged application built from downloads; the same application packaged, an MSIX loose layout with an identity registered under Developer Mode and started by its app ID, in the Windows Sandbox guest (experimental) and on a machine with Developer Mode on; the packaged build runs the whole contract as a column of its own, "WinUI 3 (packaged)", activated with the session's arguments, and is activated for its own URI scheme), ManualA control's context flyout opens behind another window through UI Automation, which brings the window forward to show it; a far item of a virtualised ListView is reached by setting its scroll viewer's position to where the item should be (item 150 of 200 in about 3 s); .NET MAUI reads as WinUI: an application built with the MAUI workload in the downloaded SDK passes the form, the far list item and the modal page—
UWP, hosted by ApplicationFrameHostCalculator, Settings, PhotosFullTest (Calculator)The helper tells which process each frame hosts; keys need the foreground (XAML ignores many posted keys); a minimized window shows nothing until restore(); a suspended app is woken in the background; an app is activated with arguments (the Store Notepad with a file) and for a URI (ms-settings:display), and launch({ uri }) activates the scheme's handler and names its process; in the Windows Sandbox (experimental) the helper runs in the guest, where a packaged application registered there starts by its app ID; the image has no Store apps, so none is driven there—
Java Swing, AWTtext editors, enterprise Java clientsGoodTest (java-apps.md)Java 8 and 32-bit runtimes (Temurin 8 x86 among them) through their own bridge; in the Windows Sandbox (experimental) only an application that brings its own runtime (a jpackage image) runs, read through the bridge in the guest; custom components show nothing to the bridge, and their text is read off the screen (an editor that paints its own text, verified); a long JList lists only the rows it shows: a locator scoped to it is reached by dragging its scroll bar's thumb with the real mouse to where the item should be (file 150 of 200 in about 3 s), and the wheel pages it otherwise; a JTable is a table by column (its header's labels head its columns), one without a header by the column count its AccessibleTable reports, but is not paged—
JavaFXDBeaver wizards, JavaFX clientsGoodTest (an application run from source on the machine's JDK with the OpenJFX SDK)JavaFX implements UI Automation itself (no Access Bridge); fields named by Label.labelFor; the form, tree, far list and modal all pass. A modal shown from a button's handler blocks the Invoke call, as elsewhere; one shown after the handler returns does not—
SWT / Eclipse RCPEclipse, DBeaverGoodTest (an application run from the SWT jar from Maven Central)Native controls through their MSAA proxies, as Win32; names through SWT's Accessible. Passed every shared-contract scenario—
Qt Widgetsengineering toolsGoodTest (a PySide6 application)Qt takes a drop-down's choice, a tree item's expansion, a list's scrolling and an item's selection only from real input: SPART-Desk ends with it where nothing in the background took, so these need the window in the foreground; a far list item takes about 30 s with the wheel, as the list shows few rows and Qt exposes neither a scroll pattern that takes a position nor its scroll bar, so nothing sets its position from outside; between pages the list is looked at alone. Fields labelled by buddy labels, and by the text beside them without, are found; custom-painted widgets show nothing. A QTableWidget reports its cells flat under it, with the table's AutomationId: they are grouped into rows by place, and found by columnreading the screen covers painted widgets
Qt Quick / QMLmodern Qt applicationsGoodTest (a PySide6 application)A combo box opens only for the mouse and reports no value, so selectOption clicks and says nothing confirms the choice; it reports itself collapsed while its list shows, and expand() counts it open by its items. A list reports a highlighted item unselected: only a delegate's Accessible.selected reports it. A ListView keeps the rows it created above and below its view and reports them on screen: SPART-Desk tells its view by where the rows are, pages it with the wheel and pages on toward a row it will not scroll into view (item 150 of 200 in about 28 s, the list looked at alone between pages; it exposes no scroll pattern and no scroll bar, so its position cannot be set). A label named by Accessible.name shows its text only on screen. Controls without Accessible.name are named by the text beside them—
Flutter (Windows)cross-platform Flutter desktop applicationsGoodTest (an application built with the Flutter SDK)SPART-Desk's helper reads the window's widgets. Flutter reports a drop-down as a button named "label\nvalue", which getByLabel finds by its label and selectOption presses (as does expand()), choosing the item's button its menu shows; an ExpansionTile as a text with no expand state (click it); and a ListView as a named group of buttons stacked in a column that overflows it, which SPART-Desk reads as the list it is and pages with the wheel, the only thing that moves it (item 150 of 200 in about 40 s); text fields refuse UI Automation's value, so fill() clicks and types with real input. hover() and scroll({ wheel }) are the real mouse over a control's middle—
Avaloniacross-platform .NETGoodTest (an application built from downloads)A TreeViewItem reports no name and no expand state: it is named by the caption read inside it, and expand()/collapse() toggle the expander button it holds and read the state from it; its window reports its client area as its bounds, and text read off its picture is placed by its frame; a far item of a virtualised ListBox is reached by setting its scroll viewer's position to where the item should be (item 150 of 200 in about 1 s, in front or behind another window)—
ElectronVS Code, Slack, DiscordGood–FullTest (an Electron application of SPART-Desk's own, with the shared contract, its editors and a native dialog; electron-apps.md)A rich-text editor that keeps its own model (Slate, Lexical, ProseMirror: the composers of Slack, Discord, Teams, Notion) is typed into in the background, never given a value its model would not hear, and what its Send posts is checked. A Monaco editor ignores set-value (an empty one is typed into in the background; one holding text needs real input); a page takes chords only as real input; a working window's tree is large (VS Code: 2 000 controls and more); snapshot({ root }) reads only inside its root, while a chained locator reads the whole window; canvases are pixels. An HTML <select>'s option is chosen with real input only; an ARIA tree expands, a far listbox option is found, and a modal window is answered in the background; an HTML table's row is found by its cells, its header cells (reported as cells) heading its columns. Slack unverified.—
React Native for Windowsthe Microsoft Store, the Xbox app, Office's and Teams' newer surfacesFullTest (an application built from the React Native template with its Fabric C++ app, the "React Native (Windows)" column of the matrix: 66 of 87 cases pass, 19 are declared n/a for what React Native's core lacks or its platform never reports)Its views are UI Automation elements only with a role, a label and accessible set, and act on UI Automation's patterns only through accessibility actions; no picker, slider, spin box, menu bar, tabs, tree, grid or drag and drop in React Native's core (an application builds them from views); a press hears the left button and the device, no other button, no modifier key, no pen pressure; its native tooltip is outside the tree; a list that virtualises drops its items out of view from the tree; its scroll pattern takes no position, which SPART-Desk sees through and pages with the wheel—
WebView2 hostsnew Outlook, Teams 2, hybrid applications, Blazor HybridFull (the page)Test (a Windows Forms host, electron-apps.md; a Blazor Hybrid page, a MAUI application's BlazorWebView in WinUI 3's WebView2, found by its address https://0.0.0.1/ and driven through the page's labels; WinUI 3's WebView2 runtime shows the page in a widget window of its own over the host window, which the application's windows include, so a launch names the host's process)As Electron, rich-text editors included; characters posted in the background do not always arrive (read back, posted again, then typed with real input); Teams and new Outlook unverified (they need a signed-in account)—
IE WebBrowser hostsWindows Forms, VB6 and Delphi applications that show a page in the WebBrowser control (TWebBrowser), HTML HelpGoodTest (a Windows Forms host of the control, ie-webbrowser-apps.md)The engine (MSHTML) reports the page through Windows' MSAA proxy: roles, names, values, states, an element's id as its AutomationId; a page in IE7's default document mode reads too. An ARIA tree item named after every line under it is named by its own text; a tab, menu item or tree item without Invoke is clicked, since the engine takes their selection and expansion patterns without telling the page; a table's cells, each reported in a row of its own, are read by row. The host gives a page no pointer events (legacy input mode) and IE11 no spin box and no fieldset group, which the matrix declares. HTML Help, VB6 and Delphi hosts unverified—
Tk (tkinter)Python toolsPartialTest (a tkinter/ttk application; its panes read as widgets)One window handle per widget, each an unnamed pane with no role: what each paints tells its widget (a button, a check box with its state, a combo box with its value and its popup, an input box, a list, a tree with its indicators), named by the label beside or above it, acted on with real input in the foreground. The form, the tree, the modal and the far list item pass: a painted list is paged with the wheel over its picture, leaping toward a numbered item (item 150 of 200 in about 19 s). A selected row reads as text (its highlight is flattened for the reader); expand() presses a painted combo box open and finds its list by the lines read around it; Tk 9.0 still shows UI Automation nothing—
wxWidgets (wxPython)Audacity, FileZilla, Python toolsGoodTest (a wxPython application)Native controls through their MSAA proxies, names through a wx.Accessible of the control's own (wx.Window.SetName names it to nothing outside the application); the form, tree, modal and far list item (150 of 200 in about 9 s, through the list box's window) pass—
One toolkit hosted in the otherElementHost in Windows Forms, WindowsFormsHost in WPFFullTest (dotnet-apps.md)The hosted controls are plain WPF or Windows Forms controls, read as one tree across the host—
CEF applicationsSpotify, Steam, enterprise clientsPartial–GoodTest (a CefSharp host of the Electron application's pages)With force-renderer-accessibility the page reads as Electron's does; without it the first look sees the pane and nothing in it, then Chromium turns accessibility on for the client that asked and the page follows. A launch can pass the switch in argsreading the screen while the page is opaque
Delphi VCL, C++BuilderERP, medical, point of saleGoodTest (vcl-apps.md), Manual (WinSCP, HeidiSQL)Labels, speed buttons and grid cells are read off the screen, so clicks on them need the foreground; AutomationIds are window handles; a 32-bit application's windows are read by the 32-bit build of the helper (vcl-apps.md)—
Delphi FireMonkeycross-platform DelphiPixelsExpectedOne window handle, no UI Automation—
VB6, ActiveX, PowerBuilderlegacy line-of-businessPartialExpectedMSAA only; windowless controls, DataWindows and third-party grids are opaquereading the screen
OfficeWord, Excel, OutlookGood (ribbon, dialogs) / Partial (document)Expected (automation-interfaces.md)Excel's cells and Word's body are read whole through the application's own automation interface (app.automation); on screen, Word's body is one textOffice itself verified
SCADA/EMS operator consolesutility operator consolesPartial (the console)Test (a console of that kind, SPART-Desk's own)The navigator, tabulars, alarm summary, menus and control dialogs are plain controls; the one-line, banner, trend and dashboard are drawn, so they are read off the screen, clicked with real input in the foreground, and told apart by colour through a picture. A device outside the view is reached through the display's own search. Trend curves and gauge needles are not read—
Games, DirectX, OpenGL, CAD canvases—Pixels / BlockedTest (an application drawing through Direct3D 11 flip and blit swap chains, DirectComposition and OpenGL, read behind another window)Windows drawn on the graphics card capture as any window; what captures black is display affinity, protected video and a locked session, which no capture lifts, and a snapshot and a screen locator's error say so; anti-cheat drops injected input; a view that turns or pans by relative raw-input deltas (a game engine's camera) hears our moves as absolute positions only, so it does not move (input-engine.md)—
Remote desktop, RemoteApp, Citrix, VM consoles—PixelsExpectedOne picture of a remote screen; compressionrecognising such windows and reading them first
Console and text-mode applicationscmd, PowerShell, CLI toolsPartialExpectedThe buffer reads as one text— (a terminal testing tool fits better)
Elevated applicationsRun as administrator, MMC, regeditBlocked unless the runner is elevatedTest (the credential prompt, the same rule; an application run as administrator by hand)Windows (UIPI) keeps a process from reading or driving one of a higher integrity level: an action fails at once with elevation_required, and a snapshot notes why it is empty; run the test runner elevated (elevated.md)—
InstallersMSI, WiX Burn, Inno Setup, NSIS, ClickOnceGood (their dialogs)Test (an NSIS installer built from the NSIS zip, installing under the profile and uninstalled again; a per-user MSI built with the WiX toolset, walked through Windows Installer's dialogs and removed silently, and a ClickOnce deployment installed through its security dialog, started from its .appref-ms and removed through its maintenance dialog; installers.md)Their pages are Win32 dialogs of common controls, walked by their buttons; an installer that needs elevation needs an elevated runner (elevated.md); a ClickOnce dialog belongs to the ClickOnce service, named as the target; WiX Burn and Inno Setup unverifiedthe Windows Sandbox runtime (experimental)
Shell surfacestray icons, notifications, taskbarGoodTest (desktop.shell(), in the Windows Sandbox (experimental) too)Names are in the display language; the flyouts close through their taskbar button (a posted Escape is ignored); a notification's text may read "Private"; another display's taskbar through shell({ display }); an application that lives in the tray until its window is shown is attached by processName and reached through its icon (launch({ target: { processName }, windowTimeout: 0 }))—
File Explorerfolders, the Details view, the Open and Save dialogs' itemsGoodTest (a folder the test makes, behind another window)An item's invoke opens it, so a click selects it and a double click opens it (a folder in the same window), in the background; the Details view reads as a table (table({ root: getByRole("list", { name: "Items View" }) }), each property's value, a folder's Size empty); an item's context menu is asked for through UI Automation (selected first, as a right click selects it), and Explorer brings its window forward to show it; the rename box is named after what it holds, so it is found by its class (UIRenameTextElement). Names show without extensions by default—
Applications of several processesout-of-process dialogs, updatersGoodTest (an application of several processes, locally and in the Windows Sandbox (experimental))Windows of the processes an application started count only for a launched one; one attached to spans what its windows own—
Windows' own dialogscredential prompt, print dialog, Open and Save, folder pickers, task dialogsGood–PartialTest (credential prompt; Notepad's print dialog; the common dialogs and task dialogs)The credential prompt is one of the application's windows, but it runs at a higher integrity level, so Windows (UIPI) keeps its fields out of UI Automation and its input out of reach: its text is read off the screen, and acting in it fails with elevation_required unless the test runner runs elevated; app.credentialPrompt() is the prompt Windows ties to the application, never another's (elevated, where the prompt has no owner, through the helper's wait-chain link) (elevated.md); the print dialog is an application of its own (attach({ processName: "PrintDialog" })), readable in full—

Never automatable, by design of Windows​

  • The UAC consent prompt, which runs on the secure desktop.
  • Video protected by DRM, which captures black.
  • A locked session, and session 0 (services).
  • Games whose anti-cheat rejects injected input.