{"id":23415,"date":"2025-11-25T04:23:33","date_gmt":"2025-11-25T09:23:33","guid":{"rendered":"https:\/\/qxf2.com\/blog\/?p=23415"},"modified":"2025-11-25T04:23:33","modified_gmt":"2025-11-25T09:23:33","slug":"getting-started-with-windows-desktop-automation-using-appium-and-winappdriver","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/getting-started-with-windows-desktop-automation-using-appium-and-winappdriver\/","title":{"rendered":"Getting Started with Windows Desktop Automation Using Appium and WinAppDriver"},"content":{"rendered":"<p>Windows desktop automation has become much easier with Appium and WinAppDriver. If you have worked with mobile automation before, the workflow will feel familiar. You start a server, define capabilities, locate elements, and interact with the application. The same concepts now apply to Windows desktop apps.<\/p>\n<p>In this post, we will walk you through a minimal and practical example of desktop automation using Python, Appium, and WinAppDriver. To keep things simple, we will automate the Notepad application and show how to launch the app, clear existing text, type new content, verify it, and close the application.<\/p>\n<p>We use Appium with WinAppDriver because this is the approach Microsoft now recommends for Windows desktop automation after deprecating CodedUI. At <a href=\"https:\/\/qxf2.com\/?utm_source=windows_desktop_automation&#038;utm_medium=click&#038;utm_campaign=From%20blog\" target=\"_blank\">Qxf2<\/a>, we prefer tools that are well-supported and future-friendly, so adopting <a href=\"https:\/\/techcommunity.microsoft.com\/blog\/testingspotblog\/winappdriver-and-desktop-ui-test-automation\/1124543\" target=\"_blank\">Microsoft&#8217;s recommended stack<\/a> was the natural choice.<\/p>\n<p>The goal of this guide is to give you a clean, functional setup that you can reuse when automating more complex Windows applications. This tutorial is beginner-friendly and does not require any prior experience with desktop automation.<\/p>\n<hr>\n<h4>1. Prerequisites and Setup:<\/h4>\n<p>Before we start writing automation for a Windows desktop app, we need to install and configure a few tools. Follow the steps below to prepare your environment.<\/p>\n<h5>1.1 Python Installation and Environment Setup<\/h5>\n<p><strong>a. Install Python:<\/strong><\/p>\n<ol>\n<li>Download Python from the <a href=\"https:\/\/www.python.org\/downloads\/\" target=\"_blank\">official website<\/a>.<\/li>\n<li>During installation, check the box <strong>Add Python to PATH<\/strong>.<\/li>\n<li>Verify installation with:\n<pre lang='python'>\r\npython --version\r\npip --version<\/pre>\n<\/li>\n<\/ol>\n<p><strong>b. Create and Activate a Virtual Environment:<\/strong><\/p>\n<p>Creating a virtual environment keeps your dependencies clean and isolated.<\/p>\n<ol>\n<li>Create a new environment:\n<pre lang='python'>python -m venv venv-notepad-automated-test<\/pre>\n<\/li>\n<li>Activate it:\n<pre lang='python'>venv\\Scripts\\activate<\/pre>\n<p>You should now see (venv-notepad-automated-test) in your terminal prompt.<\/li>\n<\/ol>\n<p><strong>c. Install Appium Python Client<\/strong><br \/>\nInside the activated virtual environment, install the Appium Python client:<\/p>\n<pre lang='python'>pip install Appium-Python-Client<\/pre>\n<p>This library allows your Python scripts to communicate with the Appium server.<\/p>\n<h5>1.2 Install Windows App Driver (WinAppDriver):<\/h5>\n<p>Head over to the <a href=\"https:\/\/github.com\/microsoft\/WinAppDriver\/releases\" target=\"_blank\">WinAppDriver Releases page<\/a> and download the latest stable build. Install it just like any other Windows application.<br \/>\nWinAppDriver provides the communication bridge that Appium uses to control Windows desktop applications.<\/p>\n<h5>1.3 Install Node.js and npm:<\/h5>\n<p>Download the Windows installer from the <a href=\"https:\/\/nodejs.org\/en\" target=\"_blank\">official Node.js website<\/a>.<br \/>\nThe installer automatically includes npm, and you&#8217;ll need npm to install and run Appium.<\/p>\n<h5>1.4 Install Appium Server:<\/h5>\n<p>Once Node.js is ready, install Appium globally using npm:<\/p>\n<pre lang='python'>npm install -g appium<\/pre>\n<p>This sets up the Appium command-line server that powers your automation.<br \/>\nFor more details, refer <a href=\"https:\/\/appium.io\/docs\/en\/3.0\/quickstart\/install\/\" target=\"_blank\">Appium Quickstart Guide<\/a>. <\/p>\n<h5>1.5 Install the Appium Windows Driver:<\/h5>\n<p>Install Appium windows driver to add support for Windows desktop automation by running:<\/p>\n<pre lang='python'>appium driver install windows<\/pre>\n<p>Verify the Windows driver installation by running following command:<\/p>\n<pre lang='python'>appium driver list<\/pre>\n<p>The output should confirm that the Windows driver is installed.<\/p>\n<h5>1.6 Start the Appium server:<\/h5>\n<p>Run following command on terminal to start the Appium Server:<\/p>\n<pre lang='python'>appium<\/pre>\n<p>Keep this terminal window running during your tests.<\/p>\n<h5>1.7 Install Locator Tools:<\/h5>\n<p>You will need locator tools to inspect UI elements and identify attributes such as AutomationId, Name, ClassName, and NativeWindowHandle. These tools are required for writing reliable selectors for desktop automation.<\/p>\n<p><strong>Windows Inspector (Inspect.exe)<\/strong><br \/>\nThis tool is required. It is the primary utility for inspecting Windows UI Automation elements. You will use it to read attributes, verify tree hierarchy, and extract the NativeWindowHandle when attaching to a running app.<\/p>\n<p><strong>Appium Inspector<\/strong><br \/>\nThis tool is highly recommended. It helps you preview elements through an Appium session, validate XPath expressions, and explore the UI structure more easily. Appium Inspector is especially useful when working with legacy apps where attributes are not unique.<\/p>\n<p>If you are new to these tools, refer to the earlier posts for detailed guidance:<\/p>\n<p><a href=\"https:\/\/qxf2.com\/blog\/how-to-use-windows-inspector\/\" target=\"_blank\">How to use Windows Inspector to write selectors for Windows UI or Desktop App<\/a><\/p>\n<p><a href=\"https:\/\/qxf2.com\/blog\/how-to-use-appium-inspector-along-with-windows-inspector\/\" target=\"_blank\">How to use Appium Inspector along with Windows Inspector<\/a><\/p>\n<p>These tools together will help you build stable and accurate locators before writing automation scripts.<\/p>\n<hr>\n<h4>2. Understanding Desired Capabilities for Windows Desktop Apps<\/h4>\n<p>Before writing our automation script, we need to tell Appium which Windows application we want to launch and how to interact with it. This configuration is done using desired capabilities.<\/p>\n<p>Desired capabilities are sent to the Appium server when a new session is created. They describe the target platform, the application to launch, and the device we are testing on. For Windows desktop automation, the set of capabilities is small and easy to understand.<\/p>\n<p>Below are the capabilities used in our Notepad example.<\/p>\n<h5>&#8220;app&#8221; Capability:<\/h5>\n<p>This tells Appium which Windows application to launch.<\/p>\n<pre lang='python'>options.set_capability(\"app\", \"notepad.exe\")<\/pre>\n<p>You can provide:<\/p>\n<ul>\n<li>the executable name (for apps like Notepad), or<\/li>\n<li>the full path to an EXE, or<\/li>\n<li>an App User Model ID for packaged applications.<\/li>\n<\/ul>\n<p>In our example, &#8220;notepad.exe&#8221; is enough.<\/p>\n<h5>&#8220;platformName&#8221; Capability:<\/h5>\n<p>This is always &#8220;Windows&#8221; for desktop automation.<\/p>\n<pre lang='python'>options.set_capability(\"platformName\", \"Windows\")<\/pre>\n<h5>&#8220;deviceName&#8221; Capability:<\/h5>\n<p>This value is required but not validated. You can put any string here.<\/p>\n<pre lang='python'>options.set_capability(\"deviceName\", \"WindowsPC\")<\/pre>\n<p>Putting it all together.<\/p>\n<p>Here is the exact configuration from your working script:<\/p>\n<pre lang='python'>\r\noptions = WindowsOptions()\r\noptions.set_capability(\"app\", \"notepad.exe\")\r\noptions.set_capability(\"platformName\", \"Windows\")\r\noptions.set_capability(\"deviceName\", \"WindowsPC\")\r\n<\/pre>\n<p>These three capabilities are enough to launch Notepad through Appium and WinAppDriver.<\/p>\n<p>In the next section, we will look at how to use these capabilities inside a simple Python script to automate a Windows desktop application.<\/p>\n<hr>\n<h4>3. Writing Your First Desktop Automation Script (Python):<\/h4>\n<p>Now that you understand the setup and desired capabilities, let&#8217;s walk through creating your first python Windows desktop automation script using Appium and WinAppDriver. We will automate a simple workflow in Notepad. First, we will build the script step by step, and then you will see the complete working example. The goal is to understand how each part of the script works before running the final example.<\/p>\n<p>We will follow a simple test flow:<\/p>\n<ol>\n<li>Launch Notepad<\/li>\n<li>Locate the text editor area<\/li>\n<li>Clear any existing content<\/li>\n<li>Verify the content is cleared<\/li>\n<li>Add new text<\/li>\n<li>Verify the text is added successfully<\/li>\n<li>Close the application<\/li>\n<\/ol>\n<p>Let us walk through the script step by step. <\/p>\n<h5>Step 1: Create Windows options and set capabilities<\/h5>\n<p>We begin by defining the capabilities required for Appium to launch the Notepad application. These capabilities tell Appium which app to start and on which device.<\/p>\n<pre lang='python'>\r\noptions = WindowsOptions()\r\noptions.set_capability(\"app\", \"notepad.exe\")\r\noptions.set_capability(\"platformName\", \"Windows\")\r\noptions.set_capability(\"deviceName\", \"WindowsPC\")\r\n<\/pre>\n<h5>Step 2: Start the automation session<\/h5>\n<p>To interact with the application, we open a session using Appium that connects to the WinAppDriver server.<\/p>\n<pre lang='python'>\r\ndriver = webdriver.Remote(\r\n    command_executor=\"http:\/\/127.0.0.1:4723\",\r\n    options=options\r\n)\r\n<\/pre>\n<h5>Step 3: Locate the Notepad text input area<\/h5>\n<p>Using the name attribute of Notepad&#8217;s editable area, we fetch the main text control where input operations will be performed.<\/p>\n<pre lang='python'>\r\ntext_area = driver.find_element(\"name\", \"Text editor\")\r\n<\/pre>\n<p>Refer to the screenshot below to see how we obtained the locator values for the text area. We used Windows Inspector to inspect the element.<br \/>\n<figure id=\"attachment_23466\" aria-describedby=\"caption-attachment-23466\" style=\"width: 900px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Get-Notepads-test-area-locator-with-Windows-Inspector.png\" data-rel=\"lightbox-image-0\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Get-Notepads-test-area-locator-with-Windows-Inspector-1024x430.png\" alt=\"Get Notepad&#039;s text area locator with Windows Inspector\" width=\"900\" height=\"378\" class=\"size-large wp-image-23466\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Get-Notepads-test-area-locator-with-Windows-Inspector-1024x430.png 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Get-Notepads-test-area-locator-with-Windows-Inspector-300x126.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Get-Notepads-test-area-locator-with-Windows-Inspector-768x322.png 768w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Get-Notepads-test-area-locator-with-Windows-Inspector-1536x645.png 1536w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Get-Notepads-test-area-locator-with-Windows-Inspector.png 1846w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/a><figcaption id=\"caption-attachment-23466\" class=\"wp-caption-text\">Get Notepad&#8217;s text area locator with Windows Inspector<\/figcaption><\/figure><\/p>\n<h5>Step 4: Clear existing content<\/h5>\n<p>Before adding new content, the script selects all existing text and deletes it.<\/p>\n<pre lang='python'>\r\ntext_area.send_keys(Keys.CONTROL, 'a')\r\ntext_area.send_keys(Keys.DELETE)\r\n<\/pre>\n<h5>Step 5: Verify the text cleared successfully<\/h5>\n<p>To ensure the clear operation worked, the script checks the value of the text field. A cleared text area reports a None value.<\/p>\n<pre lang='python'>\r\ncleared_value = text_area.get_attribute(\"Value.Value\")\r\nassert cleared_value == None, \"Text area not cleared properly!\"\r\n<\/pre>\n<h5>Step 6: Add new text<\/h5>\n<p>Now we type the new text into Notepad. This confirms that Appium can send keystrokes to a Windows application.<\/p>\n<pre lang='python'>\r\nnew_text = \"Writing text using Appium with WinAppDriver\"\r\ntext_area.send_keys(new_text)\r\n<\/pre>\n<h5>Step 7: Verify the new text<\/h5>\n<p>To validate correctness, the script reads back the text and checks whether it matches what was typed.<\/p>\n<pre lang='python'>\r\nadded_value = text_area.get_attribute(\"Value.Value\")\r\nassert added_value == new_text, \"Text not added correctly!\"\r\n<\/pre>\n<h5>Step 8: Close the application<\/h5>\n<p>Once all validations are complete, the script ends the session by closing Notepad.<\/p>\n<pre lang='python'>\r\ndriver.quit()\r\n<\/pre>\n<h5>Full Working Example<\/h5>\n<p>Below is the complete test script. You can save this file as test_notepad.py and run it directly.<br \/>\n<strong>Note:<\/strong> This is highly simplified code to make this post illustrative. We do not use this quality of the code at clients.<\/p>\n<pre lang='python'>\r\n#test_notepad.py\r\nfrom appium import webdriver\r\nfrom appium.options.windows import WindowsOptions\r\nfrom selenium.webdriver.common.keys import Keys\r\nimport time\r\n\r\ndef test_notepad_app():\r\n    # --- Appium Windows Options ---\r\n    options = WindowsOptions()\r\n    options.set_capability(\"app\", \"notepad.exe\")\r\n    options.set_capability(\"platformName\", \"Windows\")\r\n    options.set_capability(\"deviceName\", \"WindowsPC\")\r\n\r\n    # --- Start session (Appium must be running) ---\r\n    driver = webdriver.Remote(\r\n        command_executor=\"http:\/\/127.0.0.1:4723\",\r\n        options=options\r\n    )\r\n\r\n    time.sleep(1)\r\n\r\n    # --- Locate the Notepad text area ---\r\n    text_area = driver.find_element(\"name\", \"Text editor\")\r\n\r\n    # --- Step 1: Clear existing content ---\r\n    text_area.send_keys(Keys.CONTROL, 'a')\r\n    text_area.send_keys(Keys.DELETE)\r\n\r\n    # --- Step 2: Verify content is cleared ---\r\n    cleared_value = text_area.get_attribute(\"Value.Value\")\r\n    assert cleared_value == None, \"Text area not cleared properly!\"\r\n    print(\"\u2713 Cleared existing text if any and verified it\")\r\n\r\n    # --- Step 3: Add new text ---\r\n    new_text = \"Writing text using Appium with WinAppDriver\"\r\n    text_area.send_keys(new_text)\r\n\r\n    # --- Step 4: Verify text added ---\r\n    added_value = text_area.get_attribute(\"Value.Value\")\r\n    assert added_value == new_text, \"Text not added correctly!\"\r\n    print(\"\u2713 Added text and verified it\")\r\n\r\n    # --- Step 5: Close Notepad ---\r\n    driver.quit()\r\n    print(\"\u2713 Test completed successfully\")\r\n\r\nif __name__ == \"__main__\":\r\n    test_notepad_app()\r\n<\/pre>\n<hr>\n<h4>4. Running Your Test<\/h4>\n<p>Once your script is ready, running the test is straightforward. Before executing the test, make sure the following components are running correctly.<\/p>\n<h5>Step 1: Start the Appium server<\/h5>\n<p>Appium must be started manually and running in the background. Open a new command prompt and run:<\/p>\n<pre lang='python'>appium<\/pre>\n<p>You should see a message saying the server is listening on port 4723. Look at the screenshot below.<br \/>\n<figure id=\"attachment_23398\" aria-describedby=\"caption-attachment-23398\" style=\"width: 900px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Start-Appuim-Server.png\" data-rel=\"lightbox-image-1\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Start-Appuim-Server-1024x435.png\" alt=\"Start Appuim Server\" width=\"900\" height=\"382\" class=\"size-large wp-image-23398\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Start-Appuim-Server-1024x435.png 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Start-Appuim-Server-300x127.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Start-Appuim-Server-768x326.png 768w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Start-Appuim-Server.png 1062w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/a><figcaption id=\"caption-attachment-23398\" class=\"wp-caption-text\">Start the Appuim Server<\/figcaption><\/figure><br \/>\nIn background, it starts WinAppDriver.<\/p>\n<h5>Step 2: Run the Python test<\/h5>\n<p>Navigate to the folder containing your test script and execute:<\/p>\n<pre lang='python'>python test_notepad_app.py<\/pre>\n<p>Expected outcome:<br \/>\nIf everything is configured correctly, you will see Notepad open, clear any existing text, type new content, verify it, and close automatically.<br \/>\nThe console will display success messages such as:<\/p>\n<pre>\r\n\u2713 Cleared existing text if any and verified it\r\n\u2713 Added text and verified it\r\n\u2713 Test completed successfully\r\n<\/pre>\n<p>Look at the below screenshot.<br \/>\n<figure id=\"attachment_23470\" aria-describedby=\"caption-attachment-23470\" style=\"width: 739px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Run-the-test-Expected-Output.png\" data-rel=\"lightbox-image-2\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Run-the-test-Expected-Output.png\" alt=\"Run the test - Expected Output\" width=\"739\" height=\"228\" class=\"size-full wp-image-23470\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Run-the-test-Expected-Output.png 739w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2025\/11\/Run-the-test-Expected-Output-300x93.png 300w\" sizes=\"auto, (max-width: 739px) 100vw, 739px\" \/><\/a><figcaption id=\"caption-attachment-23470\" class=\"wp-caption-text\">Run the test &#8211; Expected Output<\/figcaption><\/figure><\/p>\n<p>If you see these messages, your Windows desktop automation setup is working.<\/p>\n<hr>\n<p>Hope you found this walkthrough helpful and were able to get your first Windows desktop app test running. Once you see a simple script execute end-to-end, the rest of the automation journey becomes much easier. You now know how to launch a Windows app, locate elements, interact with controls, validate results, and close the application cleanly. These are the core building blocks for any desktop automation project.<\/p>\n<p>Automating Windows applications with Appium and WinAppDriver is a practical way to test legacy systems, internal tools, and native Windows programs. In this blog, you set up the required tools, understood the key capabilities, and wrote a complete Python script for Notepad.<\/p>\n<p>With this foundation in place, you can start exploring more complex applications and workflows. The same approach works for calculators, file explorers, ERP systems, and most Windows apps that expose UI Automation properties. This is a solid base to build reliable and maintainable desktop automation across your projects.<\/p>\n<hr>\n<h4>Need Desktop Automation Experts?<\/h4>\n<p>Desktop automation is a niche skill that is both hard to hire for and difficult to maintain. At <a href=\"https:\/\/qxf2.com\/contact?utm_source=windows_desktop_automation&#038;utm_medium=click&#038;utm_campaign=From%20blog\">Qxf2<\/a>, we have engineers who truly enjoy this type of deep technical testing. Our open-source framework already supports Windows desktop applications, making it easier for us to deliver results quickly and reliably. If you need dependable, high-quality desktop automation, we have the expertise to help.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Windows desktop automation has become much easier with Appium and WinAppDriver. If you have worked with mobile automation before, the workflow will feel familiar. You start a server, define capabilities, locate elements, and interact with the application. The same concepts now apply to Windows desktop apps. In this post, we will walk you through a minimal and practical example of [&hellip;]<\/p>\n","protected":false},"author":12,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[50,38,441,195],"tags":[],"class_list":["post-23415","post","type-post","status-publish","format-standard","hentry","category-appium","category-automation","category-desktop-automation","category-windows"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/23415","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=23415"}],"version-history":[{"count":36,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/23415\/revisions"}],"predecessor-version":[{"id":23477,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/23415\/revisions\/23477"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=23415"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=23415"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=23415"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}