New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

appium-flaui-native-driver

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

appium-flaui-native-driver

Appium 3 Windows driver backed by a compiled C# FlaUI sidecar (UIA3/UIA2 + MSAA legacy).

beta
latest
Source
npmnpm
Version
0.1.0-beta.28
Version published
Weekly downloads
8
-33.33%
Maintainers
1
Weekly downloads
 
Created
Source

appium-flaui-native-driver

A custom Appium 3 driver for Windows desktop UI automation, built directly on FlaUI (UI Automation / UIA3) through a compiled, self-contained C#/.NET sidecar. It automates Universal Windows Platform (UWP), Windows Forms (WinForms), Windows Presentation Foundation (WPF), and Classic Windows (Win32) apps on Windows 10 and later.

Designed W3C-first and stability-first, it offers:

  • Native FlaUI backend — every interaction goes through FlaUI's UIA3 layer (patterns, conditions, real SendInput mouse/keyboard), not PowerShell string-scraping. This unlocks the full UIA surface and is faster and more reliable for traditional desktop apps.
  • Crash- and hang-resistant — UIA runs in a separate sidecar process behind five anti-hang layers. A frozen target app fails that one command in seconds; the session and the Appium server survive.
  • Rich attribute retrieval — every direct UIA property, pattern dot-notation (Value.Value, Toggle.ToggleState, …), LegacyIAccessible.* (MSAA) with shorthand aliases, Is*PatternAvailable flags, and a single "all" dump — matching what inspect.exe shows.
  • Full XPath 1.0 engine — 13 axes, all core functions, @*, ControlType aliases, correct positional semantics, with structural parts pushed down to native UIA conditions.
  • Platform-specific commands — direct window manipulation, real input gestures, clipboard (text + image), file transfer, and more, via windows: <command>.
  • Zero end-user setup — the sidecar ships as a self-contained single-file .exe. No .NET install, no Developer Mode, no separate WinAppDriver server.

Status: BETA (appium-flaui-native-driver@beta; win-x64, win-x86, win-arm64). The command surface below is implemented and verified end-to-end on real Windows machines. Canonical, always-current API/status: docs/03-reference/appium-api.md.

📑 Table of Contents

🚀 Getting Started

Installation

The driver is built for Appium 3. Install it from npm:

appium driver install --source=npm appium-flaui-native-driver@beta

Or from a local checkout/tarball containing prebuilt/<arch>/FlaUiSidecar.exe:

appium driver install --source=local /path/to/appium-flaui-native-driver

Prerequisites

  • Host OS: Windows 10 / 11, or Windows Server 2016+ with the Desktop Experience feature (x64; arm64 is cross-built but not yet run-verified). Server Core has no desktop and is not supported.
  • No .NET install — the sidecar is self-contained. No Developer Mode or extra software.
  • Appium 3 (appium@^3.0.0), Node ≥ 20.19, npm ≥ 10.

[!NOTE] Package size. Each sidecar embeds the .NET runtime, so the prebuilt binary is ~180 MB (x64). This is the deliberate cost of zero end-user setup and offline reliability (see docs/04-design/decisions.md ADR-013).

⚙️ Configuration

The driver supports the following capabilities, grouped by prefix in order — appium: (session & app) → ms: (Windows-compat) → flaui: (engine tuning):

CapabilityDescriptionDefaultExample
platformNameMust be Windows (case-insensitive).(Required)Windows
appium:automationNameMust be FlaUINative (case-insensitive).(Required)FlaUINative
appium:appPath to the executable to launch (or Root for the whole desktop). The driver owns a launched app and closes it on session end.(None)C:\Windows\System32\notepad.exe
appium:appTopLevelWindowAttach to an existing window by hex HWND.(None)0x40344
appium:appNameAttach to a running app whose window TITLE matches this regex (case-insensitive).(None).*Notepad
appium:processNameAttach to a running app by exact exe name (case-insensitive, .exe optional).(None)notepad.exe
appium:createSessionTimeoutPoll budget (ms) to wait for an attach target to appear before failing.6000030000
appium:appArgumentsArguments passed to the app on launch.(None)--debug
appium:appWorkingDirWorking directory for the launched app.(None)C:\Temp
appium:shouldCloseAppOn session end, close the app started via app (incl. a single-instance app app fell back to attaching). Apps reached via appTopLevelWindow/appName/processName are never closed.truefalse
appium:newCommandTimeoutStandard Appium cap (provided by base-driver, not redeclared here): seconds the server waits for the next command before auto-ending an idle session. 0 = never. Also drives the default for flaui:idleTimeout (+120s).60600
appium:prerun{ script } — PowerShell to run before the session starts (requires the power_shell feature).(None){script: '...'}
appium:postrun{ script } — PowerShell to run on session teardown (requires the power_shell feature).(None){script: '...'}
appium:typeDelayPer-character delay (ms) for send_keys / windows: keys typing.0100
appium:includeContextElementInSearchFind-from-element searches include the context element itself.truefalse
appium:convertAbsoluteXPathToRelativeFromElementWhen true, a find-from-element XPath starting with // is rewritten to .// (treat a leading // as "from this context element").falsetrue
ms:waitForAppLaunchSeconds to wait after launch for the app's window to appear.03
ms:forcequitKill the app process (instead of a graceful close) on session deletion.falsetrue
flaui:backendUI Automation API: uia3 = modern COM UIA (full pattern set, recommended); uia2 = managed wrapper — try only if a legacy control misbehaves under UIA3.uia3uia2
flaui:operationTimeoutMain per-op watchdog (ms) — every UIA op must finish within this or it's aborted as timeout and the worker recycled (the core anti-hang bound). Raise for legitimately slow ops.3000030000
flaui:connectionTimeout / flaui:transactionTimeoutLow-level UIA COM timeouts (ms), kept below the watchdog so a stuck COM call bails on its own first. Rarely tuned.min(20000, opTimeout−5000)5000
flaui:elementTableMaxSize of the sidecar's RuntimeId→element cache (FIFO). Bump for huge trees / very long sessions.(sidecar default)5000
flaui:idleTimeoutSidecar self-exits after this idle time (orphan guard). Defaults to newCommandTimeout + 120s, so setting newCommandTimeout alone suffices; newCommandTimeout: 0 disables it.newCommandTimeout + 120000600000
flaui:autoRecycleOpt-in. true = silently recycle the sidecar on a transport failure. false (default) = a dead sidecar fails the session (invalid session id) so you start a fresh one.falsetrue

[!NOTE]

  • A target is required — exactly one of app / appTopLevelWindow / appName / processName. When several are given, the attach target resolves appTopLevelWindow → processName → appName → app → Root (exact identifiers before fuzzy patterns).
  • App lifecycle — app launches the app and closes it on session end (the driver owns it; unless shouldCloseApp: false, and ms:forcequit kills instead of closing). appTopLevelWindow / appName / processName attach to a running app and leave it running.
  • PowerShell timeout is per-call, not a capability: execute('powershell', [{script\|command, timeout?}]) (default 60000 ms). PowerShell runs out-of-scheduler, so flaui:operationTimeout does not bound it.
  • flaui: caps tune the sidecar — most sessions never set any. The timeout ones form the nested anti-hang chain (UIA < watchdog < RPC < hard-deadline), see docs/02-architecture/stability.md.
  • Prefixes: ms: = WinAppDriver-compatible names · flaui: = engine tuning · appium: = standard/session.

💡 Example Usage

Python (Appium-Python-Client)

from appium import webdriver
from appium.options.common import AppiumOptions

options = AppiumOptions()
options.set_capability('platformName', 'Windows')
options.set_capability('appium:automationName', 'FlaUINative')
options.set_capability('appium:app', 'C:\\Windows\\System32\\notepad.exe')

driver = webdriver.Remote('http://127.0.0.1:4723', options=options)
try:
    el = driver.find_element('name', 'Text Editor')
    el.send_keys('Hello from FlaUI')
finally:
    driver.quit()

JavaScript (WebdriverIO)

const { remote } = require('webdriverio');

const driver = await remote({
  hostname: '127.0.0.1', port: 4723,
  capabilities: {
    platformName: 'Windows',
    'appium:automationName': 'FlaUINative',
    'appium:app': 'C:\\Windows\\System32\\notepad.exe',
    // attach instead: 'appium:appTopLevelWindow': '0x40344'
    // whole desktop:  'appium:app': 'Root'
  },
});

✨ Key Features

Element Location

The driver supports the standard Appium/WinAppDriver location strategies, mapped to UIA attributes as shown in inspect.exe:

StrategyDescriptionExample
accessibility idThe AutomationId attribute.CalculatorResults
class nameThe ClassName attribute.TextBlock
idAlias of accessibility id (matches AutomationId). The dotted RuntimeId (e.g. 42.333896.3.1) is what the driver returns as each element's identity.CalculatorResults
nameThe Name attribute.Calculator
tag nameThe ControlType short name (e.g. Button, Text).Text
xpathFull XPath 1.0 over any inspect-visible attribute; structural parts run as native UIA conditions.(//Button)[2]

Finding from an element (scoped/descendant search) is supported.

Attribute Retrieval

Retrieve element details with get_attribute / get_property. Resolution is done natively in FlaUI:

Supported Attributes

  • Standard UIA Properties — AutomationId, Name, ClassName, RuntimeId, ControlType, IsEnabled, IsOffscreen, BoundingRectangle, ProviderDescription, IsDialog, and any other direct UIA property by name.
  • Pattern-Specific Properties — dot-notation Pattern.Property resolved via FlaUI's pattern objects:
    • Value.Value, Value.IsReadOnly
    • Toggle.ToggleState
    • ExpandCollapse.ExpandCollapseState
    • RangeValue.Value / .Minimum / .Maximum / .SmallChange
    • Window.CanMaximize / .CanMinimize / .IsModal / .WindowVisualState
    • Selection.CanSelectMultiple, Grid.RowCount / .ColumnCount, and other patterns.
  • Pattern-availability flags — Is<Pattern>PatternAvailable (e.g. IsInvokePatternAvailable, IsTogglePatternAvailable), derived from FlaUI's pattern library for the current framework.
  • Legacy / MSAA Properties —
    • Dot-notation: LegacyIAccessible.Name, LegacyIAccessible.Role, LegacyIAccessible.Value, .State, .Description, .Help, .KeyboardShortcut, .DefaultAction, .ChildId.
    • Shorthand aliases: legacyname, legacyvalue, legacyrole, legacystate, legacydescription, legacyhelp, legacykeyboardshortcut, legacydefaultaction, legacychildid.
  • Special keyword — "all": returns every resolvable attribute as a JSON string (per W3C, single attributes are returned as strings; the "all" dump is JSON). The same data is available as a native object via execute('windows: getAttributes', el).
  • Synthetic Text — a best-effort text value (TextPattern → ValuePattern → Name → LegacyIAccessible).
# A single pattern/legacy attribute (returned as a string)
value      = element.get_attribute('Value.Value')
legacy_name = element.get_attribute('LegacyIAccessible.Name')
can_invoke  = element.get_attribute('IsInvokePatternAvailable')

# Everything at once, as a JSON string
all_attributes = element.get_attribute('all')

[!NOTE] Page source is available via the standard driver.page_source and via execute('windows: getPageSource', { elementId }) for a subtree.

Stability & Anti-Hang

Unlike in-process drivers, every UIA call runs inside a separate sidecar process on a dedicated, cancellable STA worker. The timeouts are nested so the gentlest layer fires first (UIA ≈20s < watchdog 30s < RPC 35s < hard-deadline 40s; see docs/02-architecture/stability.md):

  • UIA ConnectionTimeout / TransactionTimeout (flaui:connectionTimeout / flaui:transactionTimeout) — defaulted below the watchdog so a frozen COM call self-aborts before a thread needs poisoning.
  • Per-operation wall-clock watchdog (flaui:operationTimeout).
  • STA worker poisoning — a hung worker thread is abandoned and replaced.
  • Serialized operation queue — one UIA call at a time, no cross-talk.
  • Hard-deadline + honest failure — every RPC settles within the hard-deadline even if the inner layers fail; a dead/unresponsive sidecar then fails the session with invalid session id (kill the wedged process, tell the client to create a new session). Opt into silent recycle/re-attach with flaui:autoRecycle: true.

Orphan guard: the sidecar self-exits on parent (Appium) death (stdin-EOF heartbeat) and after flaui:idleTimeout (default 5 min) with no command — so a forgotten session can't leave a ~180 MB process behind.

The net effect: a frozen target app fails that command in seconds (not a 60 s hang), the session and Appium server keep working, and a truly dead backend ends the session cleanly instead of hanging or silently lying.

PowerShell Execution

Run PowerShell directly from a test. Requires the power_shell insecure feature (see Security). PowerShell is an opt-in convenience here — it is not the backend (the backend is FlaUI).

# Execute a command string
driver.execute_script('powershell', {'command': 'Get-Process Notepad'})

# Execute a script string
driver.execute_script('powershell', {'script': '$p = Get-Process Notepad; $p.Kill()'})

# Set the timeout for this call (ms); defaults to 60000 if omitted
driver.execute_script('powershell', {'command': 'Start-Sleep 5; "done"', 'timeout': 10000})

🛠 Platform-Specific Extensions

All extensions are invoked via driver.execute_script("windows: <methodName>", args), where args is a single object of named parameters (this driver uses Appium 3's executeMethodMap).

  • To target an element, pass { 'elementId': element.id }. As a convenience you may also pass the WebElement itself as the sole argument (driver.execute_script('windows: invoke', element)) — it serializes to the W3C element key, which the command accepts.
  • Extra parameters go in the same object, e.g. { 'elementId': element.id, 'value': 'New Value' }. (Unlike some Windows drivers, a trailing positional value argument is not read — put it in the object.)

Mouse & Pointer

windows: click

A single (or repeated) mouse click via real SendInput.

NameTypeRequiredDescriptionDefault
elementIdstringnoElement to click. With no x/y, clicks the element's clickable point (falls back to rect center, with scrollIntoView). With x/y, treats them as an offset from the element's top-left.—
x, ynumbernoClick coordinates. Without elementId, absolute screen coordinates; with elementId, an offset. If both are omitted with no element, uses the current cursor position.cursor pos
buttonstringnoleft, middle, right.left
timesnumbernoNumber of clicks (e.g. 2 for double-click).1
modifierKeysstring[] | stringnoKeys held during the click: Shift, Ctrl, Alt, Win.—
durationMsnumbernoHold time between press and release.0
interClickDelayMsnumbernoPause between clicks when times > 1.100
driver.execute_script('windows: click', {'elementId': element.id, 'button': 'right', 'times': 2})
driver.execute_script('windows: click', {'x': 500, 'y': 300})

windows: clickAndDrag

A click-and-drag gesture.

NameTypeRequiredDescriptionDefault
startElementId / startX / startYstring / numbernoDrag start (element center, element-relative offset, or absolute / cursor).cursor pos
endElementId / endX / endYstring / numbernoDrag end (same semantics as start).cursor pos
buttonstringnoleft, middle, right.left
durationMsnumbernoDrag duration; 0 does an instant drag.0
modifierKeysstring[] | stringnoKeys held during the drag.—
driver.execute_script('windows: clickAndDrag', {
    'startElementId': src.id, 'endElementId': dst.id, 'durationMs': 2000})

windows: hover

Moves the cursor from a start point to an end point.

NameTypeRequiredDescriptionDefault
elementId / x / ystring / numbernoTarget point (element center, element-relative offset, or absolute / cursor).cursor pos
modifierKeysstring[] | stringnoKeys held during the move.—
durationMsnumbernoMove duration; 0 moves instantly.0

windows: scroll

A mouse-wheel scroll gesture.

NameTypeRequiredDescriptionDefault
elementId / x / ystring / numbernoScroll anchor point.cursor pos
deltaXnumbernoHorizontal wheel movement (positive = right).0
deltaYnumbernoVertical wheel movement (positive = forward/away).0
amountnumbernoWheel-notch count. With deltaX/deltaY it multiplies them; on its own (no deltas) it scrolls vertically by that many notches (positive = forward/away).1
modifierKeysstring[] | stringnoKeys held during the scroll.—
driver.execute_script('windows: scroll', {'elementId': element.id, 'deltaY': -120})

Keyboard

windows: keys

Customized keyboard input via real SendInput.

NameTypeRequiredDescription
actionsKeyAction[] | KeyActionyesOne or more key actions.

KeyAction — { text } to type a string, { virtualKeyCode, down } for explicit key down/up, and { pause } to insert a delay (ms) between actions.

driver.execute_script('windows: keys', {'actions': [
    {'virtualKeyCode': 0x10, 'down': True},   # Shift down
    {'text': 'Hello World'},
    {'virtualKeyCode': 0x10, 'down': False},  # Shift up
]})

windows: typeDelay

Sets the per-character delay (ms) for the session.

NameTypeRequiredDescription
delaynumberyesDelay in milliseconds.
driver.execute_script('windows: typeDelay', {'delay': 100})

Element Operations

Each targets an element ({ elementId }, or the element passed as the sole argument) and calls the corresponding UIA pattern in FlaUI.

CommandUIA PatternDescription
windows: invokeInvokeActivate the element (button press, link, etc.).
windows: setValueValueReplace the element's value: { elementId, value }. Falls back to select-all + delete + keyboard typing for controls without ValuePattern. (The W3C send_keys command instead appends into existing content, matching Selenium/WinAppDriver; use clear() then send_keys to replace from a test.)
windows: getValueValueRead the element's value.
windows: toggleToggleToggle a checkbox/toggle control.
windows: expandExpandCollapseExpand the element.
windows: collapseExpandCollapseCollapse the element.
windows: scrollIntoViewScrollItemScroll the element into view.
windows: setFocus(UIA SetFocus)Set keyboard focus to the element.
windows: getAttributes—Return the full attribute set as a native object (object form of get_attribute('all')).
driver.execute_script('windows: invoke', element)                                  # element as sole arg
driver.execute_script('windows: setValue', {'elementId': element.id, 'value': 'New Value'})
driver.execute_script('windows: toggle', {'elementId': element.id})

Selection Management

For controls supporting the Selection / SelectionItem patterns. Each targets an element ({ elementId }).

CommandDescription
windows: selectSelect the element.
windows: addToSelectionAdd the element to the current selection.
windows: removeFromSelectionRemove the element from the current selection.
windows: isMultipleWhether the container supports multiple selection.
windows: selectedItemThe currently selected item.
windows: allSelectedItemsAll currently selected items.

Window Management

Window-state commands (WindowPattern) target the window element ({ elementId }):

CommandDescription
windows: maximizeMaximize the window.
windows: minimizeMinimize the window.
windows: restoreRestore the window to normal state.
windows: closeClose the window.

Bringing a window to the front:

windows: setWindowForeground

Brings a window to the foreground using an escalating strategy — basic foreground first, then stronger methods (topmost toggle, minimize/restore) if needed. This is the robust counterpart to a plain setFocus.

NameTypeRequiredDescription
elementIdstringnoThe window element to bring forward.

windows: click already performs a basic bring-on-top before clicking. Use setWindowForeground when a window needs stronger foregrounding (e.g. it stays behind another window).

windows: setProcessForeground

Brings the main window of a named process to the foreground.

NameTypeRequiredDescription
processstringyesProcess name, e.g. notepad.exe.

System & State

windows: setClipboard / windows: getClipboard

Get or set the Windows clipboard as plaintext or a PNG image.

NameTypeRequiredDescriptionDefault
b64Content (set only)stringyesBase64-encoded content to set.—
contentTypestringnoplaintext or image.plaintext
driver.execute_script('windows: setClipboard', {'b64Content': 'SGVsbG8=', 'contentType': 'plaintext'})
text = driver.execute_script('windows: getClipboard', {'contentType': 'plaintext'})

windows: launchApp / windows: closeApp

Launch or close the app under test within the current session.

windows: getPageSource

Returns the UIA page source. With { elementId }, returns the subtree rooted at that element.

File transfer

Standard Appium file commands (insecure features): execute('pushFile', {...}), execute('pullFile', {...}), execute('pullFolder', {...}).

Actions API

The standard W3C Actions API (pointer + key) is fully supported via driver.perform_actions(...) / driver.release_actions().

🔒 Security / Insecure Features

powershell (incl. appium:prerun), pullFile/pullFolder, and pushFile are Appium insecure features. This driver targets isolated VM environments and never trades a feature for security (ADR-015).

Recommended (dev/test, isolated VM) — enable everything with one flag:

appium --relaxed-security

Locked-down alternative — enable only specific features (the --allow-insecure CLI flag does not parse multiple scoped features reliably, so use a config file):

// appium-config.json
{ "server": { "allow-insecure": [
  "flauinative:power_shell", "flauinative:pull_file", "flauinative:push_file"
] } }
appium --config appium-config.json

Trust boundary (no sandbox): once enabled, power_shell runs arbitrary code and the file commands read/write any path — by design. Enable only when the server and all clients are trusted.

🛠 Development

npm install          # install dependencies
npm run build        # transpile TypeScript -> JS
npm run test:unit    # cross-platform unit tests (no Windows needed)

Rebuilding the sidecar requires the .NET 10 SDK (end users do not — the prebuilt exe is self-contained):

dotnet publish sidecar -r win-x64 --self-contained -p:PublishSingleFile=true -p:EnableCompressionInSingleFile=true

Project docs

Start at docs/README.md — a top-down reading map (overview → architecture → reference).

DocWhat
docs/01-overview/Introduction & quickstart
docs/02-architecture/Overview (C4), request-flow, stability (timeouts/anti-hang), backend-flaui, sidecar-internals
docs/03-reference/appium-api.mdCanonical API reference — W3C + windows: commands & status
docs/03-reference/rpc-protocol.mdThe TS↔C# JSON seam (ops, envelope, errors)
docs/03-reference/capabilities.md · locators-xpath.mdCapabilities; locators & XPath
docs/04-design/ADRs, known-issues, security
docs/05-operations/clean-reinstall.mdFast clean wipe-and-reinstall on Windows test boxes
docs/internal/Maintainer notes (changelog, audit, subagents)

Known gaps / roadmap

-windows uiautomation raw-condition locator, rawView page source, active-element / getDeviceTime, and run-verification of the win-arm64 prebuilt on real ARM hardware. Screen recording is out of scope (ADR-012). See docs/04-design/known-issues.md.

Keywords

appium

FAQs

Package last updated on 09 Jul 2026

Related posts