Understand what your app is showing
Inspect the live UI hierarchy and capture screenshots to investigate layout, content, and element state in your .NET app.
VisualTree tools connect what you see on screen with the elements that make up the live UI. Use hierarchy snapshots, focused node inspection, and screenshots to investigate layout or content problems.
Install
dotnet add package Ansight.Tools.VisualTree
Register the Suite
using Ansight;
using Ansight.Tools.VisualTree;
var options = Options.CreateBuilder()
.WithVisualTreeTools()
.WithReadOnlyToolAccess()
.Build();
Registration API
WithVisualTreeTools(): registers the full visual tree, screenshot, and diagnostic overlay suite. No suite-specific configuration is currently required.WithReadOnlyToolAccess(): exposes visual tree, screenshot, node inspection, and read-only overlay tools.WithReadWriteToolAccess(): also exposes overlay mutation tools for drawing, updating, and clearing diagnostic overlays.
Visual-Tree Providers
Visual-tree capture is provider-based. VisualTreeProviderRegistry always exposes the platform hierarchy as native, and Ansight.Tools.Maui registers a separate maui source.
Additional frameworks can implement IVisualTreeProvider and register a named source:
using Ansight.Tools.VisualTree;
using var registration = VisualTreeProviderRegistry.Register(
new CustomVisualTreeProvider());
The provider supplies a stable Source, a display name, GetVisualTreeAsync(...), and InspectNodeAsync(...). Pass source to ui.get_visual_tree or ui.inspect_node; omitting it selects native. VisualTreeProviderRegistry.Query() returns every registered source. Provider responses use the shared compact visual-tree v2 contract.
Local features can reuse the registry without enabling remote tools. For example, Annotated Feedback captures every registered source.
Specific Concerns
- The tools inspect the foreground scene only.
- Screenshot capture exports rendered UI content, so treat it as sensitive.
ui.get_screenshotrequires a live binary transfer channel from the paired host. The result returns transfer metadata, not inlinebase64.includeComputedStylesand detailed node inspection can reveal UI labels and accessibility metadata.- Overlay tools draw input-transparent diagnostic rectangles over the active native window.
- Overlay mutation tools require write access. Persistent overlays created with
durationMs = 0stay visible until removed or cleared.
Important: Calling screenshot tools will result in an FPS drop while the current frame is captured, encoded, and transferred. Avoid screenshot-heavy investigations during trend measurements unless visual evidence is required.
Tool Matrix
| Name | Id | Policy | Description |
|---|---|---|---|
Get Visual Tree | ui.get_visual_tree | Read | Returns the current UI hierarchy for the foreground scene. |
Get Screenshot | ui.get_screenshot | Read | Captures a screenshot of the current app scene. |
Inspect Node | ui.inspect_node | Read | Returns detailed metadata for a visual tree node. |
Show Overlay | ui.show_overlay | Write | Draws an input-transparent diagnostic overlay over the active app window. |
Get Overlay | ui.get_overlay | Read | Returns metadata and geometry for one live diagnostic overlay. |
Query Overlays | ui.query_overlays | Read | Lists live diagnostic overlays, optionally filtered by metadata. |
Update Overlay | ui.update_overlay | Write | Edits an existing diagnostic overlay. |
Remove Overlay | ui.remove_overlay | Write | Removes one diagnostic overlay by id. |
Clear Overlays | ui.clear_overlays | Write | Removes all diagnostic overlays, or overlays matching metadata filters. |
Get Visual Tree
Arguments:
includeBounds: include node bounds, defaulttrueincludeComputedStyles: include implementation-specific properties, defaultfalsemaxDepth: child depth limit, default8rootNodeId: optional subtree rootsource: optional provider source; defaults tonativemaxNodes: maximum number of nodes to capture
Returns:
platformsourcecapturedAtUtcformattypes: capture-local type-name registry referenced by nodetypeIdroot
Each compact-v2 node includes semantic role, supported actions, interactability, stable automation id when available, platform-neutral presentation data, and structural child order. See the Visual-Tree Payload Contract before consuming the JSON directly.
Example:
{
"toolId": "ui.get_visual_tree",
"arguments": {
"includeBounds": true,
"includeComputedStyles": false,
"maxDepth": 6
}
}
Get Screenshot
For the full comparison between this on-demand tool and periodic session JPEG capture, see JPEG Screenshots.
Arguments:
format:pngorjpegquality: JPEG quality1-100maxWidth: optional width capannotateNodeIds: overlay node ids on the screenshotafterScreenUpdates: Apple platforms wait for pending screen updates before rendering; defaulttrue
Returns:
platformcapturedAtUtcformatwidthheightdeliveryMode = websocket_binarywireProtocol = ansight.file-transfer.v1transferIddownloadIdsizeBytesfileNamemimeTypestatusannotationApplied
The screenshot bytes are delivered out-of-band over Ansight’s binary transfer protocol. The resident host uses transferId to map the incoming binary frames to the screenshot artifact.
Example:
{
"toolId": "ui.get_screenshot",
"arguments": {
"format": "jpeg",
"quality": 85,
"maxWidth": 1080,
"annotateNodeIds": false,
"afterScreenUpdates": true
}
}
Inspect Node
Arguments:
nodeId: required node identifierincludeAncestors: include ancestor chainincludeDescendants: include descendantsincludeProperties: include implementation-specific properties
Returns:
platformcapturedAtUtcnode- optional
ancestors - optional
descendants
Example:
{
"toolId": "ui.inspect_node",
"arguments": {
"nodeId": "root/stack[0]/button[1]",
"includeAncestors": true,
"includeDescendants": false,
"includeProperties": true
}
}
Show Overlay
ui.show_overlay creates one or more input-transparent highlight rectangles. It can target a visual-tree nodeId, an array of explicit rects, or one top-level x / y / width / height rectangle.
Arguments:
overlayId: optional caller-provided idnodeId: optional visual tree node id to highlightrects: optional array of rectangles withx,y,width,height, and optionallabelx,y,width,height: optional single rectangle coordinateslabel: optional label for a single rectanglecoordinateSpace:windoworvisualTree; defaults towindowstrokeColor: overlay stroke color; supports hex colors and common color namesfillColor: optional fill color; usenoneortransparentfor no fillstrokeWidth: stroke widthcornerRadius: rectangle corner radiusdurationMs: overlay lifetime in milliseconds; defaults to5000, use0to persist until removedmetadata: optional small scalar dictionary for caller context
Returns:
platformcapturedAtUtcoverlay
Example:
{
"toolId": "ui.show_overlay",
"arguments": {
"nodeId": "root/stack[0]/button[1]",
"strokeColor": "#FF2D55",
"fillColor": "transparent",
"strokeWidth": 3,
"cornerRadius": 6,
"durationMs": 5000,
"metadata": {
"reason": "tap-target-review"
}
}
}
Get Overlay
Arguments:
overlayId: required overlay id
Returns:
platformcapturedAtUtcoverlay
Example:
{
"toolId": "ui.get_overlay",
"arguments": {
"overlayId": "tap-target-review"
}
}
Query Overlays
Arguments:
metadataKey: optional metadata key that must be presentmetadataValue: optional value that must matchmetadataKey
Returns:
platformcapturedAtUtccountoverlays
Example:
{
"toolId": "ui.query_overlays",
"arguments": {
"metadataKey": "reason",
"metadataValue": "tap-target-review"
}
}
Update Overlay
ui.update_overlay edits an existing overlay by id. Omitted fields preserve the current overlay value. Supplying nodeId, rects, or rectangle coordinates replaces the existing geometry.
Arguments:
overlayId: required overlay idnodeId: optional replacement visual tree node id to highlightrects: optional replacement rectanglesx,y,width,height: optional replacement single rectangle coordinateslabel: optional label for a single replacement rectanglecoordinateSpace:windoworvisualTree; defaults towindowstrokeColor: optional replacement stroke colorfillColor: optional replacement fill color; usenoneortransparentto clear fillstrokeWidth: optional replacement stroke widthcornerRadius: optional replacement corner radiusdurationMs: optional replacement lifetime from now; use0to persist until removedmetadata: optional metadata dictionarymetadataMode:merge,replace, orclear
Returns:
platformcapturedAtUtcoverlay
Example:
{
"toolId": "ui.update_overlay",
"arguments": {
"overlayId": "tap-target-review",
"strokeColor": "#34C759",
"durationMs": 0,
"metadataMode": "merge",
"metadata": {
"status": "confirmed"
}
}
}
Remove Overlay
Arguments:
overlayId: required overlay id
Returns:
platformcapturedAtUtcoverlayIdremovedoverlay: removed overlay snapshot, ornullwhen no overlay matched
Example:
{
"toolId": "ui.remove_overlay",
"arguments": {
"overlayId": "tap-target-review"
}
}
Clear Overlays
Arguments:
metadataKey: optional metadata key that must be present for an overlay to be clearedmetadataValue: optional value that must matchmetadataKey
Returns:
platformcapturedAtUtccountoverlays: removed overlay snapshots
Example:
{
"toolId": "ui.clear_overlays",
"arguments": {
"metadataKey": "reason",
"metadataValue": "tap-target-review"
}
}