Content
# Appium WinCore Driver
Appium WinCore Driver is a Windows UI automation driver for
[Appium 3](https://appium.io). It automates UWP, WinForms, WPF, Win32,
and Internet Explorer applications via real UI Automation.
Key advantages over WinAppDriver:
- Faster XPath evaluation against the live UIA tree
- RawView element support (elements hidden from ContentView/ControlView)
- Standard accessibility values (`Value`, `LegacyValue`, …) on every
element, so content that MSAA-based grids (DevExpress, DataGridView,
VB6, Delphi) hide behind placeholder names is locatable without a
plugin. `windows: select` / `expand` / `collapse` check they took
effect. See [API.md](API.md#standard-accessibility-values)
- Reliable text input independent of the active keyboard layout
- WebView2, Chrome, and Edge embedded content via CDP
- Internet Explorer 11 automation via built-in IE DOM Bridge
- Built-in screen recording and clipboard API
## Installation
```bash
appium driver install --source=npm appium-wincore-driver
```
Requires Appium 3 and Windows 10 or later.
## Related projects
- [wincore-mcp](https://github.com/verisoft-ai/wincore-mcp) — MCP server for AI-agent use, driving `wincore` sessions purely over the WebDriver protocol (a separate package)
## Capabilities
All capabilities use the `appium:` prefix in W3C format
(except `platformName`).
| Capability | Type | Description |
| --- | --- | --- |
| `platformName` | string | **Required.** Must be `Windows` |
| `appium:automationName` | string | **Required.** Must be `Wincore` |
| `appium:app` | string | Exe path, UWP AUMID, or `Root` for the desktop |
| `appium:appTopLevelWindow` | string | Hex/decimal handle to attach to existing window |
| `appium:appArguments` | string | CLI arguments for the launched process |
| `appium:appWorkingDir` | string | Working directory for the process |
| `appium:appEnvironment` | object | Env vars injected for the session lifetime |
| `appium:ms:waitForAppLaunch` | number | Seconds (<=120) or ms (>120) to wait for window, including for a splash screen to give way to the main window (that splash wait defaults to 5 s when unset) |
| `appium:shouldCloseApp` | boolean | Close the window at session end. Default: `true` |
| `appium:prerun` | object | `{ script }` or `{ command }` — PowerShell before start |
| `appium:postrun` | object | `{ script }` or `{ command }` — PowerShell after end |
| `appium:isolatedScriptExecution` | boolean | Isolated PS for pre/postrun. Default: `false` |
| `appium:smoothPointerMove` | string | CSS easing for mouse (e.g. `ease-in`) |
| `appium:delayBeforeClick` | number | Milliseconds before each click |
| `appium:delayAfterClick` | number | Milliseconds after each click |
| `appium:webviewEnabled` | boolean | Enable WebView2 / Chrome / Edge CDP |
| `appium:webviewDevtoolsPort` | number | CDP port (auto-selected when omitted) |
| `appium:chromedriverExecutablePath` | string | Local Chromedriver binary |
| `appium:edgedriverExecutablePath` | string | Local msedgedriver binary |
| `appium:chromedriverCdnUrl` | string | Custom CDN for Chromedriver downloads |
| `appium:edgedriverCdnUrl` | string | Custom CDN for EdgeDriver downloads |
| `appium:ffmpegExecutablePath` | string | Local ffmpeg binary for screen recording |
| `appium:ms:forcequit` | boolean | Force-kill process on session close |
| `appium:ms:experimental-webdriver` | boolean | Experimental WebDriver features |
| `appium:logFile` | string | Path to write session logs |
| `appium:perfMetrics` | boolean | Enable per-session performance counters, read via `windows: getPerfMetrics` / reset via `windows: resetPerfMetrics`. Default: `false`. See `docs/performance.md`. |
## Examples
### Desktop root: click an icon and switch windows
```js
import { remote } from 'webdriverio';
const driver = await remote({
hostname: '127.0.0.1',
port: 4723,
path: '/',
capabilities: {
platformName: 'Windows',
'appium:automationName': 'Wincore',
'appium:app': 'Root', // attach to the Windows desktop shell
},
});
// Double-click a desktop shortcut by its accessible name
const icon = await driver.$('~Notepad');
await driver.executeScript('windows: click', [{
elementId: icon.elementId,
times: 2,
interClickDelayMs: 100,
}]);
// Give the app time to open, then switch to the new window by handle...
await driver.pause(2000);
const allHandles = await driver.getWindowHandles();
await driver.switchToWindow(allHandles[allHandles.length - 1]);
// ...or switch by title (partial, case-insensitive)
await driver.executeScript('windows: switchToWindowByTitle', [{ title: 'Notepad' }]);
// To include untitled windows (getWindowHandles omits them), use getWindows instead.
// It returns { handle, title, className } for every visible top-level window.
const windows = await driver.executeScript('windows: getWindows', []);
const popup = windows.find(w => w.className === '#32770' && w.title === '');
if (popup) await driver.switchToWindow(popup.handle);
const titleBar = await driver.$('//TitleBar');
console.log(await titleBar.getText());
// Switch back to the desktop root at any time
await driver.switchToWindow('root');
await driver.deleteSession();
```
### Windows Calculator: invoke pattern
`windows: invoke` fires the UIA InvokePattern. Prefer it over `.click()`
for controls that do not respond reliably to pointer events.
```js
import { remote } from 'webdriverio';
const driver = await remote({
hostname: '127.0.0.1',
port: 4723,
path: '/',
capabilities: {
platformName: 'Windows',
'appium:automationName': 'Wincore',
'appium:app': 'Microsoft.WindowsCalculator_8wekyb3d8bbwe!App',
},
});
async function invoke(el) {
await driver.executeScript('windows: invoke', [el]);
}
// 5 + 3 =
await invoke(await driver.$('~num5Button'));
await invoke(await driver.$('~plusButton'));
await invoke(await driver.$('~num3Button'));
await invoke(await driver.$('~equalButton'));
const display = await driver.$('~CalculatorResults');
console.log(await display.getText()); // "Display is 8"
await driver.deleteSession();
```
### Ctrl+drag via W3C Actions
Actions are processed tick by tick. All actions at the same tick index
across input sources run simultaneously. Ticks advance sequentially.
Use `pause` entries to keep sources aligned when mixing keyboard and
pointer inputs.
```js
import { remote } from 'webdriverio';
const driver = await remote({
hostname: '127.0.0.1',
port: 4723,
path: '/',
capabilities: {
platformName: 'Windows',
'appium:automationName': 'Wincore',
'appium:app': 'C:\\MyApp\\app.exe',
},
});
const source = await driver.$('~dragSource');
const target = await driver.$('~dropTarget');
await driver.performActions([
{
type: 'key',
id: 'keyboard',
actions: [
{ type: 'pause' }, // tick 0 — wait for mouse move
{ type: 'keyDown', value: '\uE009' }, // tick 1 — Ctrl key (W3C key value)
{ type: 'pause' }, // tick 2 — hold
{ type: 'pause' }, // tick 3 — hold during drag
{ type: 'keyUp', value: '\uE009' }, // tick 4 — Ctrl up
],
},
{
type: 'pointer',
id: 'mouse',
parameters: { pointerType: 'mouse' },
actions: [
{ type: 'pointerMove', duration: 0, origin: source }, // tick 0
{ type: 'pointerDown', button: 0 }, // tick 1
{ type: 'pause', duration: 300 }, // tick 2
{ type: 'pointerMove', duration: 600, origin: target }, // tick 3
{ type: 'pointerUp', button: 0 }, // tick 4
],
},
]);
await driver.releaseActions();
await driver.deleteSession();
```
### Internet Explorer (IE DOM Bridge)
The driver includes a built-in IE DOM Bridge — a 32-bit C# process
(`IEBridge.exe`) that attaches to a running IE 11 window via the
`WM_HTML_GETOBJECT` message, retrieves `IHTMLDocument2` through COM, and
routes all element commands over stdio JSON. No WebDriver protocol
proxy is involved.
IE mode activates automatically whenever a session window has the
`IEFrame` window class. This happens when:
- `appium:app` is set to the IE executable and the driver launches it, or
- `appium:appTopLevelWindow` points to an existing IE window handle, or
- `windows: switchToWindow` / `windows: switchToWindowByTitle` targets an IE window.
**Prerequisites:**
- Internet Explorer 11 at `C:\Program Files\Internet Explorer\iexplore.exe`
- Internet Options → Security: Protected Mode **disabled** on all four zones
- Internet Options → Advanced: Enhanced Protected Mode **disabled**
- View → Zoom: set to exactly **100%**
**Supported locator strategies:** `css selector`, `id`, `xpath`
Supported XPath patterns: `//tag`, `//tag[@attr="val"]`,
`//tag[contains(text(),"...")]`, `//tag[contains(@attr,"...")]`, `//tag[@attr]`
**Command support:**
| Command | Status | Notes |
|---|---|---|
| `findElement` / `findElements` | ✅ | css selector, id, xpath |
| `getTitle` | ✅ | |
| `getUrl` | ✅ | |
| `getPageSource` | ✅ | |
| `url()` | ✅ | navigate to URL |
| `getWindowHandle` | ✅ | returns HWND hex string |
| `getText(el)` | ✅ | |
| `getAttribute(el, name)` | ✅ | |
| `clear(el)` | ✅ | input / textarea only |
| `setValue(el, value)` | ✅ | input / textarea only |
| `click(el)` | ✅ / ⚠️ | works for buttons, links; broken for checkboxes and radios |
| `isDisplayed(el)` | ✅ | |
| `isEnabled(el)` | ⚠️ | unreliable for elements without an `id` attribute |
| `isSelected(el)` | ❌ | always returns `false` |
| `executeScript(script, args)` | ✅ | runs JS in the IE tab |
| `switchToFrame(id)` | ✅ | by index, element, or `null` for default content |
| `switchToParentFrame()` | ✅ | returns to default content (single-level only) |
| `getElementRect(el)` | ❌ | not implemented |
| `getElementScreenshot(el)` | ❌ | not implemented |
| `windows:` extension commands | ❌ | target the UIA tree, not the HTML DOM |
#### Launch IE and automate it
```js
import { remote } from 'webdriverio';
const driver = await remote({
hostname: '127.0.0.1',
port: 4723,
path: '/',
capabilities: {
platformName: 'Windows',
'appium:automationName': 'Wincore',
'appium:app': 'C:\\Program Files\\Internet Explorer\\iexplore.exe',
'appium:appArguments': 'https://example.com',
'appium:shouldCloseApp': true,
},
});
await driver.pause(3000); // wait for IE to load the page
await driver.setTimeout({ implicit: 5000 });
const title = await driver.getTitle();
console.log(title); // "Example Domain"
const h1 = await driver.$('h1');
console.log(await h1.getText());
await driver.deleteSession();
```
#### Attach to an already-open IE window
```js
import { remote } from 'webdriverio';
// hwnd is the decimal or hex HWND string of the IEFrame window
const driver = await remote({
hostname: '127.0.0.1',
port: 4723,
path: '/',
capabilities: {
platformName: 'Windows',
'appium:automationName': 'Wincore',
'appium:appTopLevelWindow': '0x001A0B2C',
'appium:shouldCloseApp': false,
},
});
const url = await driver.getUrl();
console.log(url);
await driver.deleteSession();
```
#### Switch into an iframe
```js
// By 0-based index
await driver.switchToFrame(0);
// By element
const frameEl = await driver.$('iframe#content');
await driver.switchToFrame(frameEl);
// Element finds are now scoped to the frame's document
const h1 = await driver.$('h1');
console.log(await h1.getText());
// Back to the top-level document
await driver.switchToFrame(null);
```
Only one level of nesting is tracked — switching into a frame while
already inside one replaces the current frame context rather than
stacking. `switchToParentFrame()` always returns to default content.
#### Switch between IE and UIA within the same session
Start a `Root` session and navigate between windows freely. The driver
switches between IE Bridge mode and UIA mode automatically based on whether
the target window is an `IEFrame`.
```js
import { remote } from 'webdriverio';
const driver = await remote({
hostname: '127.0.0.1',
port: 4723,
path: '/',
capabilities: {
platformName: 'Windows',
'appium:automationName': 'Wincore',
'appium:app': 'Root',
},
});
// Focus the IE window — IE Bridge activates automatically
await driver.executeScript('windows: switchToWindowByTitle', [{ title: 'Internet Explorer' }]);
const h1 = await driver.$('h1');
console.log(await h1.getText());
// Switch to a non-IE window — UIA resumes automatically
await driver.executeScript('windows: switchToWindowByTitle', [{ title: 'Notepad' }]);
await driver.deleteSession();
```
## API Reference
Full reference for all locator strategies, `windows:` extension
commands, WebView/CDP automation, and screen recording:
[API.md](API.md).
## Development
```bash
npm install
npm run lint
npm run build
npm run test
```
Uses [Comment Tagged Templates](https://marketplace.visualstudio.com/items?itemName=bierner.comment-tagged-templates)
for PowerShell/C syntax highlighting in VS Code.
Connection Info
You Might Also Like
No recommendations available