{"id":19846097,"url":"https://github.com/g4-api/uia-driver-server","last_synced_at":"2026-02-28T20:16:25.914Z","repository":{"id":242962540,"uuid":"809269617","full_name":"g4-api/uia-driver-server","owner":"g4-api","description":"The UiaDriver Server enables WebDriver clients, such as Selenium, to automate interactions with Windows applications. By implementing the WebDriver protocol, it allows seamless control and testing of Windows applications using familiar WebDriver commands.","archived":false,"fork":false,"pushed_at":"2024-08-06T12:13:09.000Z","size":2211,"stargazers_count":2,"open_issues_count":4,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-08-07T13:45:39.853Z","etag":null,"topics":["automated-testing","automation","csharp","desktop-automation","dotnet-core","selenium","selenium-webdriver","ui-automation","user32","webdriver","windows-automation"],"latest_commit_sha":null,"homepage":"https://github.com/g4-api/uia-driver-server","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/g4-api.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-02T07:54:12.000Z","updated_at":"2024-08-06T12:10:46.000Z","dependencies_parsed_at":"2024-06-29T20:33:40.425Z","dependency_job_id":"1d523af0-729a-4c3f-b539-72fbe77edda2","html_url":"https://github.com/g4-api/uia-driver-server","commit_stats":null,"previous_names":["g4-api/uia-driver"],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g4-api%2Fuia-driver-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g4-api%2Fuia-driver-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g4-api%2Fuia-driver-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/g4-api%2Fuia-driver-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/g4-api","download_url":"https://codeload.github.com/g4-api/uia-driver-server/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224278438,"owners_count":17285080,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automated-testing","automation","csharp","desktop-automation","dotnet-core","selenium","selenium-webdriver","ui-automation","user32","webdriver","windows-automation"],"created_at":"2024-11-12T13:10:26.015Z","updated_at":"2026-02-28T20:16:20.855Z","avatar_url":"https://github.com/g4-api.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Windows WebDriver Automation Service\n\n[![Build \u0026 Release Production](https://github.com/g4-api/uia-driver-server/actions/workflows/GithubActionsProduction.yml/badge.svg)](https://github.com/g4-api/uia-driver-server/actions/workflows/GithubActionsProduction.yml)\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Features](#features)\n- [Advantages](#advantages)\n- [Quick Start Guide](#quick-start-guide)\n  - [Prerequisites](#prerequisites)\n  - [Installation](#installation)\n- [Integration with Python](#integration-with-python)\n  - [Installing Selenium Client Libraries](#installing-selenium-client-libraries)\n  - [Example Code](#example-code)\n  - [Breakdown and Explanation](#breakdown-and-explanation)\n- [Integration with C#](#integration-with-c)\n  - [Installing Selenium Client Libraries](#installing-selenium-client-libraries-1)\n  - [Example Code](#example-code-1)\n  - [Breakdown and Explanation](#breakdown-and-explanation-1)\n- [Integration with Java](#integration-with-java)\n  - [Installing Selenium Client Libraries with Maven](#installing-selenium-client-libraries-with-maven)\n  - [Example Code](#example-code-2)\n  - [Breakdown and Explanation](#breakdown-and-explanation-2)\n- [Integration with Grid](#integration-with-grid)\n  - [Grid 4](#grid-4)\n  - [Grid 3 (Legacy)](#grid-3-legacy)\n    - [Example using `register` Command](#example-using-register-command)\n    - [Example using Configuration File](#example-using-configuration-file)\n    - [`register` Command `help` Switch](#register-command-help-switch)\n- [Using the OCR Locator](#using-the-ocr-locator)\n  - [Overview](#overview)\n  - [Passing OCR Locators as XPath or CssSelector](#passing-ocr-locators-as-xpath-or-cssselector)\n  - [Example Code](#example-code)\n    - [Python Example](#python-example)\n    - [C# Example](#c-example)\n    - [Java Example](#java-example)\n  - [OCR Inspector Tool](#ocr-inspector-tool)\n  - [Best Practices and Limitations](#best-practices-and-limitations)\n    - [Accuracy](#accuracy)\n    - [Performance](#performance)\n    - [Fallback](#fallback)\n- [Using the Coords Locator](#using-the-coords-locator)\n  - [Overview](#overview)\n  - [Passing Coords Locators as XPath or CssSelector](#passing-coords-locators-as-xpath-or-cssselector)\n  - [Example Code](#example-code)\n    - [Python Example](#python-example)\n    - [C# Example](#c-example)\n    - [Java Example](#java-example)\n  - [Cursor Coordinate Tracker Tool](#cursor-coordinate-tracker-tool)\n  - [Best Practices and Limitations](#best-practices-and-limitations)\n    - [Accuracy](#accuracy)\n    - [Performance](#performance)\n    - [Usage](#usage)\n- [Using the Object Model Locator](#using-the-object-model-locator)\n  - [Overview](#overview)\n  - [Syntax](#syntax)\n  - [Example Code](#example-code)\n    - [Python Example](#python-example)\n    - [C# Example](#c-example)\n    - [Java Example](#java-example)\n  - [Best Practices and Limitations](#best-practices-and-limitations)\n    - [Performance](#performance)\n    - [Complex Conditions](#complex-conditions)\n    - [Usage](#usage)\n\n## Overview\n\nThe **Windows WebDriver Automation Service** is a powerful tool that enables WebDriver clients, such as Selenium, to automate interactions with Windows applications. By implementing the WebDriver protocol, this service provides a seamless interface for controlling and testing Windows applications using familiar WebDriver commands.\n\n## Features\n\n- **WebDriver Protocol Compliance**: Seamlessly integrates with Selenium and other WebDriver clients.\n- **Session Management**: Create, manage, and delete UI Automation sessions.\n- **Element Interaction**: Locate and interact with UI elements using various locator strategies.\n- **Screen Capture**: Capture screenshots for visual verification and debugging.\n- **Native User32 Actions**: Perform native actions like keystrokes, mouse clicks, double-clicks, and clipboard operations.\n- **OCR-Based Element Identification**: Find elements based on their OCR (Optical Character Recognition) value, useful when elements cannot be inspected or have no automation interfaces. Use the [OCR Inspector tool](https://github.com/g4-api/ocr-inspector) to find the OCR value of the element to pass as the locator value.\n- **Static Point References**: Create elements that reference static points on the screen, even if there is no actual element there. This is useful for quick reference to static points and (X, Y)-based automation when no other options are available. Use the [Cursor Coordinate Tracker tool](https://github.com/g4-api/cursor-coordinate-tracker) to find static points values on the screen to pass as the locator value.\n\n## Advantages\n\n- **Familiar Interface**: Use standard WebDriver commands to interact with Windows applications, leveraging your existing knowledge of Selenium.\n- **Cross-Platform Automation**: Unify your web and desktop application testing under a single framework.\n- **Comprehensive API**: Detailed endpoints for a wide range of UI automation tasks, documented with Swagger for easy understanding.\n- **Community Friendly**: Welcomes contributions and provides extensive documentation to help you get started.\n\n## Quick Start Guide\n\n### Prerequisites\n\n- Basic understanding of WebDriver (e.g., Selenium)\n- .NET 8 and above\n\n### Installation\n\n1. **Download the Latest Release**:\n    - Go to the [Releases](https://github.com/g4-api/uia-driver-server/releases) page.\n    - Download the latest `Uia.DriverServer.\u003cversion\u003e-win-x64.zip` artifact.\n\n2. **Extract the Zip Artifact**:\n    ```bash\n    unzip Uia.DriverServer.\u003cversion\u003e-win-x64.zip -d uia-driver-server\n    cd uia-driver-server\n    ```\n\n3. **Run the Service**:\n    ```bash\n    ./Uia.DriverServer.exe\n    ```\n\n    The following (or similar) output is expected:\n\n    ```plaintext\n       _   _ _       ____       _                  ____\n      | | | (_) __ _|  _ \\ _ __(_)_   _____ _ __  / ___|  ___ _ ____   _____ _ __\n      | | | | |/ _` | | | | '__| \\ \\ / / _ \\ '__| \\___ \\ / _ \\ '__\\ \\ / / _ \\ '__|\n      | |_| | | (_| | |_| | |  | |\\ V /  __/ |     ___) |  __/ |   \\ V /  __/ |\n       \\___/|_|\\__,_|____/|_|  |_| \\_/ \\___|_|    |____/ \\___|_|    \\_/ \\___|_|\n\n                                       WebDriver Implementation for Windows Native\n                                                          Powered by IUIAutomation\n\n      Project:           https://github.com/g4-api/uia-driver\n      W3C Documentation: https://www.w3.org/TR/webdriver/\n      Documentation:     https://docs.microsoft.com/en-us/windows/win32/api/_winauto/\n      Open API:          /swagger\n\n\n    info: Microsoft.Hosting.Lifetime[14]\n          Now listening on: http://[::]:5555\n    info: Microsoft.Hosting.Lifetime[0]\n          Application started. Press Ctrl+C to shut down.\n    info: Microsoft.Hosting.Lifetime[0]\n          Hosting environment: Development\n    info: Microsoft.Hosting.Lifetime[0]\n          Content root path: C:\\Uia.DriverServer\n    ```\n\n## Integration with Python\n\n### Installing Selenium Client Libraries\n\nTo integrate the Windows WebDriver Automation Service with Python, you first need to install the Selenium client libraries. You can do this using pip:\n\n```bash\npip install selenium\n```\n\n### Example Code\n\nHere is a detailed example of how to set up and use the service for automating Windows applications using Python:\n\n```python\nfrom selenium import webdriver\nfrom selenium.common import WebDriverException, NoSuchElementException, StaleElementReferenceException\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.support import expected_conditions as ec\nfrom selenium.webdriver.common.options import BaseOptions\nfrom selenium.webdriver.support.wait import WebDriverWait\n\nclass UiaOptions(BaseOptions):\n    \"\"\"\n    A class to define options specific to UI Automation (UIA) for Selenium WebDriver.\n    \"\"\"\n    def __init__(self):\n        \"\"\"\n        Initializes the UiaOptions with default values.\n        \"\"\"\n        super().__init__()\n        self.app = None\n        self.uia_options = None\n\n    def to_capabilities(self):\n        \"\"\"\n        Returns the capabilities required for UIA in a dictionary format.\n        \"\"\"\n        return {\n            \"browserName\": \"Uia\",\n            \"platformName\": \"windows\",\n            \"uia:options\": self.uia_options\n        }\n\n    @property\n    def default_capabilities(self):\n        \"\"\"\n        Provides the default capabilities for the UIA WebDriver.\n        \"\"\"\n        return {\n            \"browserName\": \"Uia\",\n            \"platform\": \"windows\",\n        }\n\n# Create an instance of UiaOptions and set the application to Notepad.\noptions = UiaOptions()\n\n# Uncomment and set additional UIA options if needed.\noptions.uia_options = {\n    \"app\": \"notepad.exe\",\n    # \"arguments\": [\"param1\", \"param2\"],\n    # \"workingDirectory\": \"\u003c\u003e\",\n    # \"mount\": False,\n    # \"impersonation\": {\n    #     \"domain\": \"\u003c\u003e\",\n    #     \"username\": \"\u003c\u003e\",\n    #     \"password\": \"\u003c\u003e\",\n    #     \"enabled\": False\n    # }\n}\n\n# Initialize the WebDriver with the specified options.\ndriver = webdriver.Remote(command_executor=\"http://localhost:5555/wd/hub\", options=options)\n\n# Define exceptions to ignore during WebDriverWait.\nignored_exceptions = [WebDriverException, NoSuchElementException, StaleElementReferenceException]\n\n# Create a WebDriverWait instance with a timeout of 20 seconds.\ndriver_wait = WebDriverWait(driver, timeout=20, ignored_exceptions=ignored_exceptions)\n\n# Wait until the Notepad window is located and get the Notepad element.\nnotepad = driver_wait.until(ec.presence_of_element_located((By.XPATH, \"//Window[@ClassName='Notepad']\")))\n\n# Find the Document element within Notepad and type \"Hello from UiaDriver Server\".\ndocument = notepad.find_element(By.XPATH, \"//Document[@Name='Text editor']\")\ndocument.send_keys(\"Hello from UiaDriver Server\")\n\n# Find the File menu item and click it.\nfile_menu_item = notepad.find_element(By.XPATH, \"//MenuBar/MenuItem[@AutomationId='File']\")\nfile_menu_item.click()\n\n# Define the locator for the 'Save as' menu item and wait until it's located, then click it.\nsave_as_locator = (By.XPATH, \"//Window[@ClassName='Notepad']//MenuItem[@Name='Save as']\")\nsave_as = driver_wait.until(ec.presence_of_element_located(save_as_locator))\nsave_as.click()\n\n# Define the locator for the Cancel button in the 'Save as' dialog, wait until it's located, then click it.\ncancel_button_locator = (By.XPATH, \"//Window[@ClassName='Notepad']//Window[@Name='Save as']/Button[@Name='Cancel']\")\ncancel_button = driver_wait.until(ec.presence_of_element_located(cancel_button_locator))\ncancel_button.click()\n\n# Quit the WebDriver session.\ndriver.quit()\n```\n\n### Breakdown and Explanation\n\n1. **Import Required Modules**:\n    - `webdriver`, `WebDriverException`, `NoSuchElementException`, `StaleElementReferenceException` from `selenium`: These modules are necessary for initializing the WebDriver, handling exceptions, and interacting with UI elements.\n    - `By` and `expected_conditions` (`ec`) from `selenium.webdriver.common`: These are used for locating elements and defining expected conditions.\n    - `BaseOptions` from `selenium.webdriver.common.options`: This module is used to define custom options for the WebDriver.\n    - `WebDriverWait` from `selenium.webdriver.support.wait`: This is used to wait for specific conditions to be met before proceeding with actions.\n\n2. **Define `UiaOptions` Class**:\n    - The `UiaOptions` class inherits from `BaseOptions` and is used to define options specific to UI Automation.\n    - The `__init__` method initializes the class with default values.\n    - The `to_capabilities` method returns the capabilities required for UIA in a dictionary format.\n    - The `default_capabilities` property provides the default capabilities for the UIA WebDriver.\n\n3. **Set Application and Initialize WebDriver**:\n    - An instance of `UiaOptions` is created, and the application is set to Notepad\n\n (`notepad.exe`).\n    - Additional UIA options can be set as needed (e.g., arguments, working directory, impersonation).\n    - The WebDriver is initialized with the specified options, connecting to the WebDriver server running at `http://localhost:5555/wd/hub`.\n\n4. **Define Ignored Exceptions and Create WebDriverWait**:\n    - A list of exceptions to ignore during `WebDriverWait` is defined.\n    - An instance of `WebDriverWait` is created with a timeout of 20 seconds, ignoring the specified exceptions.\n\n5. **Interact with Notepad Application**:\n    - Wait until the Notepad window is located using the XPath locator and get the Notepad element.\n    - Find the Document element within Notepad and type \"Hello from UiaDriver Server\".\n    - Find the File menu item and click it.\n    - Define the locator for the 'Save as' menu item, wait until it's located, and click it.\n    - Define the locator for the Cancel button in the 'Save as' dialog, wait until it's located, and click it.\n\n6. **Quit the WebDriver Session**:\n    - Finally, quit the WebDriver session to clean up resources.\n\nThis integration allows you to automate interactions with Windows applications using the Windows WebDriver Automation Service and Python's Selenium WebDriver.\n\n## Integration with C#\n\n### Installing Selenium Client Libraries\n\nTo integrate the Windows WebDriver Automation Service with C#, you first need to install the Selenium client libraries. You can do this using dotnet:\n\n```bash\ndotnet add package Selenium.WebDriver\n```\n\n### Example Code\n\nHere is a detailed example of how to set up and use the service for automating Windows applications using C#:\n\n```csharp\nusing OpenQA.Selenium;\nusing OpenQA.Selenium.Remote;\n\nusing System;\nusing System.Collections.Generic;\nusing System.Threading;\n\nusing Uia.Models;\nusing Uia.Support;\n\n// Create an instance of UiaOptions and set the application to Notepad.\nvar options = new UiaOptions\n{\n    // Uncomment and set additional UIA options if needed.\n    UiaOptionsDictionary = new\n    {\n        app = \"notepad.exe\",\n        //arguments = new[] { \"param1\", \"param2\" },\n        //workingDirectory = \"\u003c\u003e\",\n        //mount = false,\n        //impersonation = new\n        //{\n        //    domain = \"\u003c\u003e\",\n        //    username = \"\u003c\u003e\",\n        //    password = \"\u003c\u003e\",\n        //    enabled = false\n        //}\n    }\n};\n\n// Initialize the WebDriver with the specified options.\nvar driver = new RemoteWebDriver(new Uri(\"http://localhost:5555/wd/hub\"), options.ToCapabilities());\n\n// Define exceptions to ignore during WebDriverWait.\nvar ignoredExceptions = new List\u003cType\u003e\n{\n    typeof(WebDriverException),\n    typeof(NoSuchElementException),\n    typeof(StaleElementReferenceException)\n};\n\n// Create a WebDriverWait instance with a timeout of 20 seconds.\nvar wait = new UiaWaiter(driver, ignoredExceptions, TimeSpan.FromSeconds(20));\n\n// Wait until the Notepad window is located and get the Notepad element.\nvar notepad = wait.Until(d =\u003e d.FindElement(By.XPath(\"//Window[@ClassName='Notepad']\")));\n\n// Find the Document element within Notepad and type \"Hello from UiaDriver Server\".\nvar document = notepad.FindElement(By.XPath(\"//Document[@Name='Text editor']\"));\ndocument.SendKeys(\"Hello from UiaDriver Server\");\n\n// Find the File menu item and click it.\nvar fileMenuItem = notepad.FindElement(By.XPath(\"//MenuBar/MenuItem[@AutomationId='File']\"));\nfileMenuItem.Click();\n\n// Define the locator for the 'Save as' menu item and wait until it's located, then click it.\nvar saveAsLocator = By.XPath(\"//Window[@ClassName='Notepad']//MenuItem[@Name='Save as']\");\nvar saveAs = wait.Until(d =\u003e d.FindElement(saveAsLocator));\nsaveAs.Click();\n\n// Define the locator for the Cancel button in the 'Save as' dialog, wait until it's located, then click it.\nvar cancelButtonLocator = By.XPath(\"//Window[@ClassName='Notepad']//Window[@Name='Save as']/Button[@Name='Cancel']\");\nvar cancelButton = wait.Until(d =\u003e d.FindElement(cancelButtonLocator));\ncancelButton.Click();\n\n// Quit the WebDriver session.\ndriver.Quit();\n\nnamespace Uia.Models\n{\n    /// \u003csummary\u003e\n    /// Represents the options for UI Automation (UIA) driver.\n    /// \u003c/summary\u003e\n    public class UiaOptions : DriverOptions\n    {\n        /// \u003csummary\u003e\n        /// Initializes a new instance of the \u003csee cref=\"UiaOptions\"/\u003e class with default values.\n        /// \u003c/summary\u003e\n        public UiaOptions()\n        {\n            UiaOptionsDictionary = null;\n        }\n\n        /// \u003csummary\u003e\n        /// Gets or sets the additional UIA options.\n        /// \u003c/summary\u003e\n        public object UiaOptionsDictionary { get; set; }\n\n        /// \u003csummary\u003e\n        /// Returns the capabilities required for UIA in a dictionary format.\n        /// \u003c/summary\u003e\n        /// \u003creturns\u003eA dictionary of capabilities.\u003c/returns\u003e\n        public override ICapabilities ToCapabilities()\n        {\n            // Generate the desired capabilities with default values\n            var capabilities = GenerateDesiredCapabilities(true);\n\n            // Set the specific capabilities for the UIA driver\n            capabilities.SetCapability(\"browserName\", \"Uia\");\n            capabilities.SetCapability(\"platformName\", \"windows\");\n            capabilities.SetCapability(\"uia:options\", UiaOptionsDictionary);\n\n            // Return the capabilities as a read-only dictionary\n            return capabilities.AsReadOnly();\n        }\n\n        /// \u003csummary\u003e\n        /// Provides the default capabilities for the UIA WebDriver.\n        /// \u003c/summary\u003e\n        /// \u003creturns\u003eA dictionary of default capabilities.\u003c/returns\u003e\n        public ICapabilities DefaultCapabilities()\n        {\n            // Generate the desired capabilities with default values\n            var capabilities = GenerateDesiredCapabilities(true);\n\n            // Set the default capabilities for the UIA driver\n            capabilities.SetCapability(\"browserName\", \"Uia\");\n            capabilities.SetCapability(\"platform\", \"windows\");\n            capabilities.SetCapability(\"uia:options\", new { app = \"Desktop\" });\n\n            // Return the capabilities as a read-only dictionary\n            return capabilities.AsReadOnly();\n        }\n    }\n}\n\nnamespace Uia.Support\n{\n    /// \u003csummary\u003e\n    /// Provides a mechanism to wait for conditions in the UI Automation (UIA) context.\n    /// \u003c/summary\u003e\n    /// \u003cparam name=\"driver\"\u003eThe WebDriver instance to be used.\u003c/param\u003e\n    /// \u003cparam name=\"ignoredException\"\u003eThe list of exceptions to ignore while waiting.\u003c/param\u003e\n    /// \u003cparam name=\"timeout\"\u003eThe timeout duration for the wait.\u003c/param\u003e\n    public class UiaWaiter(IWebDriver driver, List\u003cType\u003e ignoredException, TimeSpan timeout)\n    {\n        // Initialize the private fields with the provided values from the constructor parameters\n        private readonly IWebDriver _driver = driver;\n        private readonly List\u003cType\u003e _ignoredExceptions = ignoredException;\n        private readonly TimeSpan _timeout = timeout;\n\n        /// \u003csummary\u003e\n        /// Initializes a new instance of the \u003csee cref=\"UiaWaiter\"/\u003e class with a default timeout of 10 seconds.\n        /// \u003c/summary\u003e\n        /// \u003cparam name=\"driver\"\u003eThe WebDriver instance to be used.\u003c/param\u003e\n        public UiaWaiter(IWebDriver driver)\n            : this(driver, ignoredException: [], timeout: TimeSpan.FromSeconds(10))\n        { }\n\n        /// \u003csummary\u003e\n        /// Initializes a new instance of the \u003csee cref=\"UiaWaiter\"/\u003e class.\n        /// \u003c/summary\u003e\n        /// \u003cparam name=\"driver\"\u003eThe WebDriver instance to be used.\u003c/param\u003e\n        /// \u003cparam name=\"timeout\"\u003eThe timeout duration for the wait.\u003c/param\u003e\n        public UiaWaiter(IWebDriver driver, TimeSpan timeout)\n            : this(driver, ignoredException: [], timeout)\n        { }\n\n        /// \u003csummary\u003e\n        /// Initializes a new instance of the \u003csee cref=\"UiaWaiter\"/\u003e class with a default timeout of 10 seconds.\n        /// \u003c/summary\u003e\n        /// \u003cparam name=\"driver\"\u003eThe WebDriver instance to be used.\u003c/param\u003e\n        /// \u003cparam name=\"ignoredException\"\u003eThe list of exceptions to ignore while waiting.\u003c/param\u003e\n        public UiaWaiter(IWebDriver driver, List\u003cType\u003e ignoredException)\n            : this(driver, ignoredException, timeout: TimeSpan.FromSeconds(10))\n        { }\n\n        /// \u003csummary\u003e\n        /// Waits until a condition is met or the timeout is reached.\n        /// \u003c/summary\u003e\n        /// \u003cparam name=\"condition\"\u003eThe condition to be met.\u003c/param\u003e\n        /// \u003creturns\u003eThe web element that satisfies the condition.\u003c/returns\u003e\n        /// \u003cexception cref=\"NoSuchElementException\"\u003eThrown if the condition is not met within the timeout period.\u003c/exception\u003e\n        public IWebElement Until(Func\u003cIWebDriver, IWebElement\u003e condition)\n        {\n            // Calculate the time when the wait should timeout\n            var conditionTimeout = DateTime.Now.Add(_timeout);\n\n            do\n            {\n                try\n                {\n                    // Try to evaluate the condition\n                    return condition(_driver);\n                }\n                catch (Exception e)\n                {\n                    // Check if the exception should be ignored\n                    if (_ignoredExceptions.Exists(i =\u003e i == e.GetType()))\n                    {\n                        // Wait for a short interval before retrying\n                        Thread.Sleep(100);\n                        continue;\n                    }\n                    // Rethrow the exception if it's not to be ignored\n                    throw;\n                }\n            } while (DateTime.Now \u003c conditionTimeout);\n\n            // Throw an exception if the condition is not met within the timeout\n            throw new NoSuchElementException();\n        }\n    }\n}\n```\n\n### Breakdown and Explanation\n\n1. **Import Required Namespaces**:\n    - `OpenQA.Selenium`, `OpenQA.Selenium.Remote`: These namespaces are necessary for initializing the WebDriver and defining the options for UI Automation (UIA).\n    - `System`, `System.Collections.Generic`, `System.Threading`: These namespaces provide essential system functionalities and collections.\n\n2. **Create `UiaOptions` Instance**:\n    - An instance of `UiaOptions` is created, and the application is set to Notepad (`notepad.exe`).\n    - Additional UIA options can be set as needed (e.g., arguments, working directory, impersonation).\n\n3. **Initialize WebDriver**:\n    - The WebDriver is initialized with the specified options, connecting to the WebDriver server running at `http://localhost:5555/wd/hub`.\n\n4. **Define Ignored Exceptions and Create `UiaWaiter`**:\n    - A list of exceptions to ignore during `WebDriverWait` is defined.\n    - An instance of `UiaWaiter` is created with a timeout of 20 seconds, ignoring the specified exceptions.\n\n5. **Interact with Notepad Application**:\n    - Wait until the Notepad window is located using the XPath locator and get the Notepad element.\n    - Find the Document element within Notepad and type \"Hello from UiaDriver Server\".\n    - Find the File menu item and click it.\n    - Define the locator for the 'Save as' menu item, wait until it's located, and click it.\n    - Define the locator for the Cancel button in the 'Save as' dialog, wait until it's located, and click it.\n\n6. **Quit the WebDriver Session**:\n    - Finally, quit the WebDriver session to clean up resources.\n\nThis integration allows you to automate interactions with Windows applications using the Windows WebDriver Automation Service and C#'s Selenium WebDriver.\n\n## Integration with Java\n\nTo integrate the Windows WebDriver Automation Service with Java, you can use the Selenium WebDriver. Below is a detailed example of how to set up and use the service for automating Windows applications using Java:\n\n### Installing Selenium Client Libraries with Maven\n\nAdd the following dependencies to your `pom.xml` file to include Selenium:\n\n```xml\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.seleniumhq.selenium\u003c/groupId\u003e\n        \u003cartifactId\u003eselenium-java\u003c/artifactId\u003e\n        \u003cversion\u003e4.0.0\u003c/version\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\n### Example Code\n\n```java\npackage org.example;\n\nimport org.openqa.selenium.*;\nimport org.openqa.selenium.NoSuchElementException;\nimport org.openqa.selenium.remote.RemoteWebDriver;\nimport org.openqa.selenium.support.ui.WebDriverWait;\n\nimport java.io.Serializable;\nimport java.net.MalformedURLException;\nimport java.net.URL;\nimport java.time.Duration;\nimport java.util.*;\n\npublic class Main {\n    public static void main(String[] args) {\n        // Create an instance of UiaOptionsDictionary to configure UI Automation settings.\n        UiaOptionsDictionary uiaOptionsDictionary = new UiaOptionsDictionary();\n\n        // Set the application for the UI Automation to Notepad (notepad.exe).\n        uiaOptionsDictionary.setApp(\"notepad.exe\");\n\n        // Create an instance of UiaOptions to configure UI Automation settings.\n        UiaOptions uiaOptions = new UiaOptions();\n\n        // Assign the previously created UiaOptionsDictionary to the UiaOptions instance.\n        uiaOptions.setUiaOptionsDictionary(uiaOptionsDictionary);\n\n        // Initialize the WebDriver with the specified options.\n        WebDriver driver = null;\n        try {\n            driver = new RemoteWebDriver(new URL(\"http://localhost:5555/wd/hub\"), uiaOptions.toCapabilities());\n        } catch (MalformedURLException e) {\n            e.printStackTrace();\n        }\n\n        // Define exceptions to ignore during WebDriverWait.\n        List\u003cClass\u003c? extends Throwable\u003e\u003e ignoredExceptions = Arrays.asList(\n                WebDriverException.class,\n                NoSuchElementException.class,\n                StaleElementReferenceException.class\n        );\n\n        // Create a WebDriverWait instance with a timeout of 20 seconds.\n        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));\n        wait.ignoreAll(ignoredExceptions);\n\n        // Wait until the Notepad window is located and get the Notepad element.\n        WebElement notepad = wait.until(d -\u003e d.findElement(By.xpath(\"//Window[@ClassName='Notepad']\")));\n\n        // Find the Document element within Notepad and type \"Hello from UiaDriver Server\".\n        WebElement document = notepad.findElement(By.xpath(\"//Document[@Name='Text editor']\"));\n        document.sendKeys(\"Hello from UiaDriver Server\");\n\n        // Find the File menu item and click it.\n        WebElement fileMenuItem = notepad.findElement(By.xpath(\"//MenuBar/MenuItem[@AutomationId='File']\"));\n        fileMenuItem.click();\n\n        // Define the locator for the 'Save as' menu item and wait until it's located, then click it.\n        By saveAsLocator = By.xpath(\"//Window[@ClassName='Notepad']//MenuItem[@Name='Save as']\");\n        WebElement saveAs = wait.until(d -\u003e d.findElement(saveAsLocator));\n        saveAs.click();\n\n        // Define the locator for the Cancel button in the 'Save as' dialog, wait until it's located, then click it.\n        By cancelButtonLocator = By.xpath(\"//Window[@ClassName='Notepad']//Window[@Name='Save as']/Button[@Name='Cancel']\");\n        WebElement cancelButton = wait.until(d -\u003e d.findElement(cancelButtonLocator));\n        cancelButton.click();\n\n        // Quit the WebDriver session.\n        assert driver != null;\n        driver.quit();\n    }\n}\n\n/**\n * UiaOptions class represents the configuration options for UI Automation.\n * This class extends MutableCapabilities to allow its instances to be used as Capabilities.\n */\nclass UiaOptions extends MutableCapabilities {\n\n    // The UIA options dictionary.\n    private UiaOptionsDictionary uiaOptionsDictionary;\n\n    /**\n     * Initializes a new instance of the UiaOptions class.\n     */\n    public UiaOptions() {\n        this.uiaOptionsDictionary = new UiaOptionsDictionary();\n    }\n\n    /**\n     * Gets the UIA options dictionary.\n     */\n    public UiaOptionsDictionary getUiaOptionsDictionary() {\n        return uiaOptionsDictionary;\n    }\n\n    /**\n     * Sets the UIA options dictionary.\n     *\n     * @param uiaOptionsDictionary The UIA options dictionary.\n     */\n    public void setUiaOptionsDictionary(UiaOptionsDictionary uiaOptionsDictionary) {\n        this.uiaOptionsDictionary = uiaOptionsDictionary;\n    }\n\n    /**\n     * Converts the UiaOptions instance to a Capabilities object.\n     *\n     * @return The Capabilities object with the UIA options set.\n     */\n    public Capabilities toCapabilities() {\n        // Set the specific capabilities for the UIA driver\n        setCapability(\"browserName\", \"Uia\");\n        setCapability(\"platformName\", \"windows\");\n        setCapability(\"uia:options\", uiaOptionsDictionary.toMap());\n\n        // Return the capabilities object with the UIA options set for the driver instance creation\n        return this;\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        return super.equals(other);\n    }\n\n    @Override\n    public int hashCode() {\n        return super.hashCode();\n    }\n}\n\n/**\n * UiaOptionsDictionary class represents the configuration options for UI Automation.\n * This class implements Serializable to allow its instances to be serialized.\n */\nclass UiaOptionsDictionary implements Serializable {\n    private String app;\n    private String[] arguments;\n    private String workingDirectory;\n    private boolean mount;\n    private ImpersonationOptions impersonation;\n\n    /**\n     * Gets the application name.\n     *\n     * @return the application name.\n     */\n    public String getApp() {\n        return app;\n    }\n\n    /**\n     * Sets the application name.\n     *\n     * @param app the application name to set.\n     */\n    public void setApp(String app) {\n        this.app = app;\n    }\n\n    /**\n     * Gets the arguments for the application.\n     *\n     * @return an array of arguments.\n     */\n    public String[] getArguments() {\n        return arguments;\n    }\n\n    /**\n     * Sets the arguments for the application.\n     *\n     * @param arguments an array of arguments to set.\n     */\n    public void setArguments(String[] arguments) {\n        this.arguments = arguments;\n    }\n\n    /**\n     * Gets the working directory.\n     *\n     * @return the working directory.\n     */\n    public String getWorkingDirectory() {\n        return workingDirectory;\n    }\n\n    /**\n     * Sets the working directory.\n     *\n     * @param workingDirectory the working directory to set.\n     */\n    public void setWorkingDirectory(String workingDirectory) {\n        this.workingDirectory = workingDirectory;\n    }\n\n    /**\n     * Checks if the mount option is enabled.\n     *\n     * @return true if mount is enabled, false otherwise.\n     */\n    public boolean isMount() {\n        return mount;\n    }\n\n    /**\n     * Sets the mount option.\n     *\n     * @param mount true to enable mount, false to disable.\n     */\n    public void setMount(boolean mount) {\n        this.mount = mount;\n    }\n\n    /**\n     * Gets the impersonation options.\n     *\n     * @return the impersonation options.\n     */\n    public ImpersonationOptions getImpersonation() {\n        return impersonation;\n    }\n\n    /**\n     * Sets the impersonation options.\n     *\n     * @param impersonation the impersonation options to set.\n     */\n    public void setImpersonation(ImpersonationOptions impersonation) {\n        this.impersonation = impersonation;\n    }\n\n    /**\n     * Converts the UiaOptionsDictionary to a Map.\n     * The method ensures the app field defaults to \"Desktop\" if not set.\n     *\n     * @return a Map representing the options.\n     */\n    public Map\u003cString, Object\u003e toMap() {\n        // Set default app to \"Desktop\" if app is null or empty\n        app = app == null || app.isEmpty() ? \"Desktop\" : app;\n\n        // Create a new map to store the options\n        Map\u003cString, Object\u003e map = new HashMap\u003c\u003e();\n\n        // Add arguments to the map if not null\n        if (arguments != null) map.put(\"arguments\", arguments);\n\n        // Add workingDirectory to the map if not null\n        if (workingDirectory != null) map.put(\"workingDirectory\", workingDirectory);\n\n        // Add impersonation options to the map if not null\n        if (impersonation != null) map.put(\"impersonation\", impersonation.toMap());\n\n        // Add app and mount to the map\n        map.put(\"app\", app);\n        map.put(\"mount\", mount);\n\n        // Return the map with the options\n        return map;\n    }\n\n\n    /**\n     * ImpersonationOptions class represents the options for impersonation in UI Automation.\n     * This class implements Serializable to allow its instances to be serialized.\n     */\n    static class ImpersonationOptions implements Serializable {\n        // Initialize the fields for domain, username, password, and enabled\n        // status for impersonation options in UI Automation.\n        private String domain;\n        private String username;\n        private String password;\n        private boolean enabled;\n\n        /**\n         * Gets the domain name.\n         *\n         * @return the domain name.\n         */\n        public String getDomain() {\n            return domain;\n        }\n\n        /**\n         * Sets the domain name.\n         *\n         * @param domain the domain name to set.\n         */\n        public void setDomain(String domain) {\n            this.domain = domain;\n        }\n\n        /**\n         * Gets the username.\n         *\n         * @return the username.\n         */\n        public String getUsername() {\n            return username;\n        }\n\n        /**\n         * Sets the username.\n         *\n         * @param username the username to set.\n         */\n        public void setUsername(String username) {\n            this.username = username;\n        }\n\n        /**\n         * Gets the password.\n         *\n         * @return the password.\n         */\n        public String getPassword() {\n            return password;\n        }\n\n        /**\n         * Sets the password.\n         *\n         * @param password the password to set.\n         */\n        public void setPassword(String password) {\n            this.password = password;\n        }\n\n        /**\n         * Checks if impersonation is enabled.\n         *\n         * @return true if impersonation is enabled, false otherwise.\n         */\n        public boolean isEnabled() {\n            return enabled;\n        }\n\n        /**\n         * Sets the impersonation enabled option.\n         *\n         * @param enabled true to enable impersonation, false to disable.\n         */\n        public void setEnabled(boolean enabled) {\n            this.enabled = enabled;\n        }\n\n        /**\n         * Converts the ImpersonationOptions to a Map.\n         *\n         * @return a Map representing the impersonation options.\n         */\n        public Map\u003cString, Object\u003e toMap() {\n            // Create a new map to store the impersonation options\n            Map\u003cString, Object\u003e map = new HashMap\u003c\u003e();\n\n            // Add domain to the map if not null\n            if (domain != null) map.put(\"domain\", domain);\n\n            // Add username to the map if not null\n            if (username != null) map.put(\"username\", username);\n\n            // Add password to the map if not null\n            if (password != null) map.put(\"password\", password);\n\n            // Add enabled status to the map\n            map.put(\"enabled\", enabled);\n\n            // Return the map with the impersonation options\n            return map;\n        }\n    }\n}\n```\n\n### Breakdown and Explanation\n\n1. **Import Required Packages**:\n    - `org.openqa.selenium.*`: These packages are necessary for initializing the WebDriver, handling exceptions, and interacting with UI elements.\n    - `java.net.*`, `java.time.*`, `java.util.*`: These packages provide essential system functionalities and collections.\n\n2. **Create `UiaOptionsDictionary` Instance**:\n    - An instance of `UiaOptionsDictionary` is created, and the application is set to Notepad (`notepad.exe`).\n\n3. **Create `UiaOptions` Instance**:\n    - An instance of `UiaOptions` is created, and the `UiaOptionsDictionary` instance is assigned to it.\n\n4. **Initialize WebDriver**:\n    - The WebDriver is initialized with the specified options, connecting to the WebDriver server running at `http://localhost:5555/wd/hub`.\n\n5. **Define Ignored Exceptions and Create `WebDriverWait`**:\n    - A list of exceptions to ignore during `WebDriverWait` is defined.\n    - An instance of `WebDriverWait` is created with a timeout of 20 seconds, ignoring the specified exceptions.\n\n6. **Interact with Notepad Application**:\n    - Wait until the Notepad window is located using the XPath locator and get the Notepad element.\n    - Find the Document element within Notepad and type \"Hello from UiaDriver Server\".\n    - Find the File menu item and click it.\n    - Define the locator for the 'Save as' menu item, wait until it's located, and click it.\n    - Define the locator for the Cancel button in the 'Save as' dialog, wait until it's located, and click it.\n\n7. **Quit the WebDriver Session**:\n    - Finally, quit the WebDriver session to clean up resources.\n\nThis integration allows you to automate interactions with Windows applications using the Windows WebDriver Automation Service and Java's Selenium WebDriver.\n\n## Integration with Grid\n\nTo integrate the Windows WebDriver Automation Service with a Selenium Grid, you can register the service with either Grid 4 or Grid 3 (Legacy). Below are the detailed instructions for both versions.\n\n### Grid 4\n\nGrid 4 provides enhanced features and capabilities for managing and scaling your Selenium infrastructure. Below are the steps to register the Windows WebDriver Automation Service with Grid 4.\n\n1. **Download the Selenium Server Jar**:\n    - Download the Selenium Server jar from [Selenium Downloads](https://www.selenium.dev/downloads/).\n\n2. **Create Node Configuration File**:\n    - Create a file named `node.toml` with the following content:\n\n    ```toml\n    [node]\n    detect-drivers = false\n\n    [relay]\n    # Default UIA server endpoint\n    url = \"http://localhost:5555/wd/hub\"\n    status-endpoint = \"/status\"\n    # Optional, enforce a specific protocol version in HttpClient when communicating with the endpoint service status (e.g. HTTP/1.1, HTTP/2)\n    protocol-version = \"HTTP/1.1\"\n    configs = [\n      \"1\", \"{\\\"browserName\\\": \\\"Uia\\\", \\\"platformName\\\": \\\"windows\\\", \\\"uia:platformVersion\\\": \\\"11\\\"}\"\n    ]\n    ```\n\n    - **Note**: The `max-sessions` on Windows automation is always 1. More than that can cause unexpected behavior due to Windows trying to focus on multiple applications at the same time.\n\n3. **Start the Selenium Grid Hub**:\n    ```bash\n    java -jar selenium-server-\u003cversion\u003e.jar hub\n    ```\n\n4. **Start the Selenium Grid Node**:\n    - Use the node configuration file created in step 2. The node port can be any available port on the host machine.\n    ```bash\n    java -jar selenium-server-\u003cversion\u003e.jar node --config node.toml --port 5554\n    ```\n\nFollowing these steps will ensure that the Windows WebDriver Automation Service is properly integrated and registered with Selenium Grid 4, allowing you to leverage distributed and scalable automation for Windows applications.\n\nEnsure that the service is running and accessible at the node URL you provide to the Grid.\n\n### Grid 3 (Legacy)\n\nGrid 3 is the older version of Selenium Grid and has different registration requirements. To register the Windows WebDriver Automation Service with Grid 3, you need to start the service with the `register` command and provide a combination of switches or a configuration file.\n\n#### Example using `register` Command\n\nTo register the service with Grid 3, use the following example command:\n\n```bash\nUia.DriverServer.exe register -b Uia -ht localhost -hb http://hub-address:4444 -p 4444 -P 5555 -t \"tag1,tag2\"\n```\n\n#### Example using Configuration File\n\nAlternatively, you can use a configuration file to register the service. Create a JSON configuration file (`config.json`) with the following content:\n\n```json\n{\n  \"browserName\": \"Uia\",\n  \"host\": \"localhost\",\n  \"hub\": \"http://hub-address:4444\",\n  \"hubPort\": 4444,\n  \"hostPort\": 5555,\n  \"tags\": [\"tag1\", \"tag2\"]\n}\n```\n\nThen, register the service using the configuration file:\n\n```bash\nUia.DriverServer.exe register -c path/to/config.json\n```\n\n#### `register` Command `help` Switch\n\nYou can use the `--help` switch with the `register` command to display help information about the available options. The following output is expected:\n\n```plaintext\nC:\\Uia.DriverServer.0000.00.00.0-win-x64\u003eUia.DriverServer register --help\n\n   _   _ _       ____       _                  ____\n  | | | (_) __ _|  _ \\ _ __(_)_   _____ _ __  / ___|  ___ _ ____   _____ _ __\n  | | | | |/ _` | | | | '__| \\ \\ / / _ \\ '__| \\___ \\ / _ \\ '__\\ \\ / / _ \\ '__|\n  | |_| | | (_| | |_| | |  | |\\ V /  __/ |     ___) |  __/ |   \\ V /  __/ |\n   \\___/|_|\\__,_|____/|_|  |_| \\_/ \\___|_|    |____/ \\___|_|    \\_/ \\___|_|\n\n                                   WebDriver Implementation for Windows Native\n                                                      Powered by IUIAutomation\n\n  Project:           https://github.com/g4-api/uia-driver\n  W3C Documentation: https://www.w3.org/TR/webdriver/\n  Documentation:     https://docs.microsoft.com/en-us/windows/win32/api/_winauto/\n  Open API:          /swagger\n\n\nregister -b|--browserName -c|--config -ht|--host -hb|--hub -p|--hubPort -P|--hostPort -t|--tags -h|--help\n    -b,  --browserName  Specifies the name of the browser to use.\n    -c,  --config       Path to the configuration file.\n    -hb, --hub          Specifies the hub address.\n    -ht, --host         Specifies the node host address.\n    -p,  --hubPort      Specifies the port of the hub.\n    -P,  --hostPort     Specifies the port of the node host.\n    -t,  --tags         Specifies the tags for the node. These tags will be converted to capabilities.\n    -h,  --help         Displays help information for the specified command.\n```\n\nThis help information provides details about each command-line switch available for the `register` command, helping you configure the service appropriately for integration with Grid 3.\n\n## Using the OCR Locator\n\nThe OCR (Optical Character Recognition) locator in the UiaDriver Server allows you to find elements based on their OCR value. This is particularly useful when elements cannot be inspected or have no automation interfaces. To ensure compatibility with all W3C clients, OCR locators can be passed as XPath or CssSelector.\n\n### Overview\n\nOCR locators enable the identification of UI elements based on the text content recognized by OCR technology. Instead of relying on the exact text, OCR locators use the text identified by the OCR tool, which increases the chances of finding the element even if the text recognition is not perfect.\n\n### Passing OCR Locators as XPath or CssSelector\n\nTo use OCR locators, you need to pass them using the syntax `ocr(ocrValue)` in either XPath or CssSelector. The UiaDriver Server will interpret these locators and apply the OCR logic accordingly. Multiple OCR values can be piped using the syntax `ocr(ocrValue1|ocrValue2)`, providing fallback options if the OCR tool identifies the text differently.\n\n#### Example Code\n\nBelow are examples of how to use OCR locators in different languages by passing them as XPath or CssSelector.\n\n#### Python Example\n\n```python\nfrom selenium import webdriver\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.common.options import BaseOptions\nfrom selenium.webdriver.support.wait import WebDriverWait\nfrom selenium.webdriver.support import expected_conditions as EC\n\nclass UiaOptions(BaseOptions):\n    def __init__(self):\n        super().__init__()\n        self.app = None\n        self.uia_options = None\n\n    def to_capabilities(self):\n        return {\n            \"browserName\": \"Uia\",\n            \"platformName\": \"windows\",\n            \"uia:options\": self.uia_options\n        }\n\noptions = UiaOptions()\noptions.uia_options = {\"app\": \"notepad.exe\"}\n\ndriver = webdriver.Remote(command_executor=\"http://localhost:5555/wd/hub\", options=options)\nwait = WebDriverWait(driver, 20)\n\n# Use OCR locator passed as XPath with fallback options\nocr_locator = \"ocr('Hello from UiaDriver Server'|'Hello from Uia')\"\ndocument = wait.until(EC.presence_of_element_located((By.XPATH, ocr_locator)))\ndocument.send_keys(\"Automated text input using OCR\")\n\ndriver.quit()\n```\n\n#### C# Example\n\n```csharp\nusing OpenQA.Selenium;\nusing OpenQA.Selenium.Remote;\nusing System;\nusing System.Collections.Generic;\nusing Uia.Models;\nusing Uia.Support;\n\nvar options = new UiaOptions\n{\n    UiaOptionsDictionary = new\n    {\n        app = \"notepad.exe\"\n    }\n};\n\nvar driver = new RemoteWebDriver(new Uri(\"http://localhost:5555/wd/hub\"), options.ToCapabilities());\nvar wait = new UiaWaiter(driver, new List\u003cType\u003e { typeof(WebDriverException), typeof(NoSuchElementException) }, TimeSpan.FromSeconds(20));\n\n// Use OCR locator passed as XPath with fallback options\nstring ocrLocator = \"ocr('Hello from UiaDriver Server'|'Hello from Uia')\";\nvar document = wait.Until(d =\u003e d.FindElement(By.XPath(ocrLocator)));\ndocument.SendKeys(\"Automated text input using OCR\");\n\ndriver.Quit();\n```\n\n#### Java Example\n\n```java\npackage org.example;\n\nimport org.openqa.selenium.*;\nimport org.openqa.selenium.remote.RemoteWebDriver;\nimport org.openqa.selenium.support.ui.WebDriverWait;\n\nimport java.net.MalformedURLException;\nimport java.net.URL;\nimport java.time.Duration;\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        UiaOptionsDictionary uiaOptionsDictionary = new UiaOptionsDictionary();\n        uiaOptionsDictionary.setApp(\"notepad.exe\");\n\n        UiaOptions uiaOptions = new UiaOptions();\n        uiaOptions.setUiaOptionsDictionary(uiaOptionsDictionary);\n\n        WebDriver driver = null;\n        try {\n            driver = new RemoteWebDriver(new URL(\"http://localhost:5555/wd/hub\"), uiaOptions.toCapabilities());\n        } catch (MalformedURLException e) {\n            e.printStackTrace();\n        }\n\n        List\u003cClass\u003c? extends Throwable\u003e\u003e ignoredExceptions = Arrays.asList(\n                WebDriverException.class,\n                NoSuchElementException.class\n        );\n\n        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));\n        wait.ignoreAll(ignoredExceptions);\n\n        // Use OCR locator passed as XPath with fallback options\n        String ocrLocator = \"ocr('Hello from UiaDriver Server'|'Hello from Uia')\";\n        WebElement document = wait.until(d -\u003e d.findElement(By.xpath(ocrLocator)));\n        document.sendKeys(\"Automated text input using OCR\");\n\n        driver.quit();\n    }\n}\n```\n\n### OCR Inspector Tool\n\nTo find the OCR value of an element, you can use the [OCR Inspector tool](https://github.com/g4-api/ocr-inspector). This tool helps you obtain the OCR value that can be passed as a locator value.\n\n### Best Practices and Limitations\n\n- **Accuracy**: OCR technology identifies text based on image recognition, which may not always be perfect. Using multiple OCR values as fallback options increases the likelihood of correctly identifying elements.\n- **Performance**: OCR-based identification may be slower compared to direct element access. Use it only when other methods are not feasible.\n- **Fallback**: Implement fallback strategies by providing multiple OCR values. For example, \"Bar\" can be identified as \"8ar\" or \"88n\", so the OCR locator can be `ocr('8ar'|'88n')`.\n\n## Using the Coords Locator\n\nThe Coords (coordinates) locator in the UiaDriver Server allows you to create a virtual element that points to a static point on the screen. This is particularly useful when there are no identifiable UI elements or when you need to interact with a specific point on the screen. To ensure compatibility with all W3C clients, coordinates locators can be passed as XPath or CssSelector.\n\n### Overview\n\nCoords locators enable the creation of virtual elements based on their absolute screen coordinates. This can be especially helpful for automating interactions with applications that render elements in fixed positions or when other locators are not feasible.\n\n### Passing Coords Locators as XPath or CssSelector\n\nTo use Coords locators, you need to pass them using the syntax `coords(x,y)` in either XPath or CssSelector. The UiaDriver Server will interpret these locators and create virtual elements pointing to the specified coordinates. These virtual elements can then be interacted with using standard WebDriver Element endpoints such as `click` and `sendKeys`.\n\n#### Example Code\n\nBelow are examples of how to use Coords locators in different languages by passing them as XPath or CssSelector.\n\n#### Python Example\n\n```python\nfrom selenium import webdriver\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.common.options import BaseOptions\n\nclass UiaOptions(BaseOptions):\n    def __init__(self):\n        super().__init__()\n        self.app = None\n        self.uia_options = None\n\n    def to_capabilities(self):\n        return {\n            \"browserName\": \"Uia\",\n            \"platformName\": \"windows\",\n            \"uia:options\": self.uia_options\n        }\n\noptions = UiaOptions()\noptions.uia_options = {\"app\": \"notepad.exe\"}\n\ndriver = webdriver.Remote(command_executor=\"http://localhost:5555/wd/hub\", options=options)\n\n# Use Coords locator passed as XPath\ncoords_locator = \"coords(100,200)\"\nelement = driver.find_element(By.XPATH, coords_locator)\nelement.click()\n\ndriver.quit()\n```\n\n#### C# Example\n\n```csharp\nusing OpenQA.Selenium;\nusing OpenQA.Selenium.Remote;\nusing System;\nusing Uia.Models;\n\nvar options = new UiaOptions\n{\n    UiaOptionsDictionary = new\n    {\n        app = \"notepad.exe\"\n    }\n};\n\nvar driver = new RemoteWebDriver(new Uri(\"http://localhost:5555/wd/hub\"), options.ToCapabilities());\n\n// Use Coords locator passed as XPath\nstring coordsLocator = \"coords(100,200)\";\nvar element = driver.FindElement(By.XPath(coordsLocator));\nelement.Click();\n\ndriver.Quit();\n```\n\n#### Java Example\n\n```java\npackage org.example;\n\nimport org.openqa.selenium.*;\nimport org.openqa.selenium.remote.RemoteWebDriver;\n\nimport java.net.MalformedURLException;\nimport java.net.URL;\n\npublic class Main {\n    public static void main(String[] args) {\n        UiaOptionsDictionary uiaOptionsDictionary = new UiaOptionsDictionary();\n        uiaOptionsDictionary.setApp(\"notepad.exe\");\n\n        UiaOptions uiaOptions = new UiaOptions();\n        uiaOptions.setUiaOptionsDictionary(uiaOptionsDictionary);\n\n        WebDriver driver = null;\n        try {\n            driver = new RemoteWebDriver(new URL(\"http://localhost:5555/wd/hub\"), uiaOptions.toCapabilities());\n        } catch (MalformedURLException e) {\n            e.printStackTrace();\n        }\n\n        // Use Coords locator passed as XPath\n        String coordsLocator = \"coords(100,200)\";\n        WebElement element = driver.findElement(By.xpath(coordsLocator));\n        element.click();\n\n        driver.quit();\n    }\n}\n```\n\n### Cursor Coordinate Tracker Tool\n\nTo find the screen coordinates of a point, you can use the [Cursor Coordinate Tracker tool](https://github.com/g4-api/cursor-coordinate-tracker). This tool helps you obtain the coordinates that can be passed as a locator value.\n\n### Best Practices and Limitations\n\n- **Accuracy**: Ensure that the coordinates provided are accurate and consistent with the screen resolution and scaling settings.\n- **Performance**: Coordinates-based identification is generally faster but less reliable if the UI layout changes.\n- **Usage**: Use coordinates to create virtual elements that point to static positions on the screen. These virtual elements can be interacted with using standard WebDriver Element endpoints such as `click` and `sendKeys`.\n\n## Using the Object Model Locator\n\nThe Object Model locator in the UiaDriver Server allows you to create a virtual DOM from a specified point downward in the element tree. This enables full-featured XPath searching, which is particularly useful for refining element searches with very complicated conditions that cannot be achieved using the standard UIA XPath.\n\n### Overview\n\nObject Model locators enable the creation of a virtual DOM, allowing you to use comprehensive XPath queries. Unlike the standard UIA XPath, which is limited to logical operators and text/partial text only, the Object Model locator provides full XPath capabilities. This is useful for scenarios requiring complex element identification logic.\n\n### Syntax\n\nTo start an Object Model search, use the syntax `//Window/Pane/ObjectModel:Pane`. From this point, the Pane tree becomes a virtual DOM with full XPath capabilities. The Object Model stops at the next element in the XPath.\n\n**Warning**: Use this feature only as a last resort and on a small element scope since creating a DOM tree can be time-consuming.\n\n### Example Code\n\nBelow are examples of how to use Object Model locators in different languages by passing them as XPath.\n\n#### Python Example\n\n```python\nfrom selenium import webdriver\nfrom selenium.webdriver.common.by import By\nfrom selenium.webdriver.common.options import BaseOptions\nfrom selenium.webdriver.support.wait import WebDriverWait\nfrom selenium.webdriver.support import expected_conditions as EC\nfrom selenium.common.exceptions import WebDriverException, NoSuchElementException, StaleElementReferenceException\n\nclass UiaOptions(BaseOptions):\n    def __init__(self):\n        super().__init__()\n        self.app = None\n        self.uia_options = None\n\n    def to_capabilities(self):\n        return {\n            \"browserName\": \"Uia\",\n            \"platformName\": \"windows\",\n            \"uia:options\": self.uia_options\n        }\n\noptions = UiaOptions()\noptions.uia_options = {\"app\": \"notepad.exe\"}\n\ndriver = webdriver.Remote(command_executor=\"http://localhost:5555/wd/hub\", options=options)\nwait = WebDriverWait(driver, 20, ignored_exceptions=[WebDriverException, NoSuchElementException, StaleElementReferenceException])\n\n# Use Object Model locator passed as XPath\nobject_model_locator = \"//Window/Pane/ObjectModel:Pane//Button[@Name='Save']\"\nelement = wait.until(EC.presence_of_element_located((By.XPATH, object_model_locator)))\nelement.click()\n\ndriver.quit()\n```\n\n#### C# Example\n\n```csharp\nusing OpenQA.Selenium;\nusing OpenQA.Selenium.Remote;\nusing System;\nusing System.Collections.Generic;\nusing Uia.Models;\nusing Uia.Support;\n\nvar options = new UiaOptions\n{\n    UiaOptionsDictionary = new\n    {\n        app = \"notepad.exe\"\n    }\n};\n\nvar driver = new RemoteWebDriver(new Uri(\"http://localhost:5555/wd/hub\"), options.ToCapabilities());\n\n// Define exceptions to ignore during WebDriverWait.\nvar ignoredExceptions = new List\u003cType\u003e\n{\n    typeof(WebDriverException),\n    typeof(NoSuchElementException),\n    typeof(StaleElementReferenceException)\n};\n\n// Create a WebDriverWait instance with a timeout of 20 seconds.\nvar wait = new UiaWaiter(driver, ignoredExceptions, TimeSpan.FromSeconds(20));\n\n// Use Object Model locator passed as XPath\nstring objectModelLocator = \"//Window/Pane/ObjectModel:Pane//Button[@Name='Save']\";\nvar element = wait.Until(d =\u003e d.FindElement(By.XPath(objectModelLocator)));\nelement.Click();\n\ndriver.Quit();\n```\n\n#### Java Example\n\n```java\npackage org.example;\n\nimport org.openqa.selenium.*;\nimport org.openqa.selenium.remote.RemoteWebDriver;\nimport org.openqa.selenium.support.ui.WebDriverWait;\nimport org.openqa.selenium.support.ui.ExpectedConditions;\n\nimport java.net.MalformedURLException;\nimport java.net.URL;\nimport java.time.Duration;\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class Main {\n    public static void main(String[] args) {\n        UiaOptionsDictionary uiaOptionsDictionary = new UiaOptionsDictionary();\n        uiaOptionsDictionary.setApp(\"notepad.exe\");\n\n        UiaOptions uiaOptions = new UiaOptions();\n        uiaOptions.setUiaOptionsDictionary(uiaOptionsDictionary);\n\n        WebDriver driver = null;\n        try {\n            driver = new RemoteWebDriver(new URL(\"http://localhost:5555/wd/hub\"), uiaOptions.toCapabilities());\n        } catch (MalformedURLException e) {\n            e.printStackTrace();\n        }\n\n        // Define exceptions to ignore during WebDriverWait.\n        List\u003cClass\u003c? extends Throwable\u003e\u003e ignoredExceptions = Arrays.asList(\n                WebDriverException.class,\n                NoSuchElementException.class,\n                StaleElementReferenceException.class\n        );\n\n        // Create a WebDriverWait instance with a timeout of 20 seconds.\n        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));\n        wait.ignoreAll(ignoredExceptions);\n\n        // Use Object Model locator passed as XPath\n        String objectModelLocator = \"//Window/Pane/ObjectModel:Pane//Button[@Name='Save']\";\n        WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(objectModelLocator)));\n        element.click();\n\n        driver.quit();\n    }\n}\n```\n\n### Best Practices and Limitations\n\n- **Performance**: Creating a virtual DOM tree can be time-consuming. Use Object Model locators only as a last resort and on small element scopes.\n- **Complex Conditions**: This feature is ideal for refining element searches with complex conditions that are not feasible with standard UIA XPath.\n- **Usage**: Start the Object Model search with the syntax `//Window/Pane/ObjectModel:Pane`. The virtual DOM stops at the next element in the XPath.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fg4-api%2Fuia-driver-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fg4-api%2Fuia-driver-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fg4-api%2Fuia-driver-server/lists"}