HeadlessWindowsAutomation 1.0.2

dotnet add package HeadlessWindowsAutomation --version 1.0.2                
NuGet\Install-Package HeadlessWindowsAutomation -Version 1.0.2                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="HeadlessWindowsAutomation" Version="1.0.2" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add HeadlessWindowsAutomation --version 1.0.2                
#r "nuget: HeadlessWindowsAutomation, 1.0.2"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install HeadlessWindowsAutomation as a Cake Addin
#addin nuget:?package=HeadlessWindowsAutomation&version=1.0.2

// Install HeadlessWindowsAutomation as a Cake Tool
#tool nuget:?package=HeadlessWindowsAutomation&version=1.0.2                

Overview

HeadlessWindowsAutomation is a simple library designed for automating Windows desktop applications in a headless environment.
It leverages the C# AutomationElement API to provide a simple yet powerful interface for interacting with UI elements.
You can automate complex UI interactions and run your testing on pipelines.

To run on a pipeline, your agent must run as interactive ⇒ started from a user and not a service.
Consider using Indirect display driver (such as Virtual Display Driver) to avoid some headless limitations.

Key features

  • AutomationElementWrapper: Main class, provide automation functionalities.
    • find element(s) using the AutomationElement APIs or XPath.
      The find auto-waits for the element! You don't need to force a wait.
      That behavior is configurable using the .Config property.
    • interact with them (Click, SetText, Keyboard sub-class, etc.).
      In the end, everything will be send as message using the window handle. So it's better to interact with a component with a handle, if you don't have one then use the ClickOnLocation.
      On Windows, you can interact with components using messages even if they are not visible.
      Hence why HeadlessWindowsAutomation allows actual headless on a desktop application!
      Note that the Keyboard might not be compatible with headless, depending on your environment.
  • WindowsAPIHelper: low level utilities function around Windows APIs.
    You most likely won't use it unless you need to find elements not under your application. Like an owned top-level window.
  • ProcessHelper: utility methods for managing and interacting with processes.
    For example, can be used to find your process when you started it from a command line.

Refer to the XML documentation comments in the source code for more details.

Sample Usage

Setup

Inside your main, start your application and setup the automation:

WindowsAPIHelper.SetProcessDPIAware();  // Optional. Set DPI

// Start your app
Process myapp_cmd = Process.Start("cmd.exe", "/c myapp.exe"); // Dummy example when you don't directly start your app

// Get myapp and not just the terminal
ProcessHelper processHelper = new ProcessHelper();
processHelper.AdditionalProcessValidCheck = (Process proc) =>
{
    // we also force myapp in the name
    return proc.ProcessName.IndexOf("myapp", StringComparison.OrdinalIgnoreCase) >= 0;
};
int myapp_pid = processHelper.GetApplicationProcessIdFromParent(myapp_cmd);
Process myapp = Process.GetProcessById(myapp_pid);

// Set the root/main AutomationElementWrapper on myapp
var mainWindow = new AutomationElementWrapper(myapp.MainWindowHandle);
AutomationElementWrapper.MainWindowCallback = () => {
    return mainWindow;
};

// Automate your app
...

Automate

After Setup, automate your application:

// Set the text in an Edit control
_ = mainWindow.FindElementByXPath("//Edit[@AutomationId='123']").SetText("foo");

// Use xpath to navigate the components tree of your application
// It follows the xpath spec, refer to the doc. // is descendant, / is children, . is relative, etc.
AutomationElementWrapper subPane = mainWindow.FindElementByXPath("./Pane/Pane[@Name='Foo' and @AutomationId='1234']");
// Print the children in the console for debug, you can also use tools like Accessibility Insights or Spy++
subPane.PrintAllChildren();

AutomationElementWrapper searchBtn = subPane.FindElementByXPath("./Button[@Name='Search']")
  .Click();
Product Compatible and additional computed target framework versions.
.NET Framework net48 is compatible.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETFramework 4.8

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.2 76 10/29/2024
1.0.1 102 10/3/2024
1.0.0 101 10/2/2024