Search code examples
c#handleexternal-application

How do I get a button handle from Windows10Forms in C#?


I've been trying to find the handle for a particular help button in a program and then send a BN_CLICK message to it. To debug, I looked at the handles for the parent window and the button.

[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("User32.dll", EntryPoint = "FindWindowEx")]
private static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);

public Form1()
{
   IntPtr hWndParent = FindWindow("WindowsForms10.Window.8.app.0.2c040a7_r9_ad1", null);
   Debug.WriteLine(hWndParent,"\n");
   IntPtr button = FindWindowEx(hWndParent, IntPtr.Zero, "WindowsForms10.BUTTON.app.0.2c040a7_r9_ad1", "Help");
   Debug.WriteLine(button);
}

The debug returns a number for the hWndParent but 0 for button. I got the classes from Spy++. 1

This might be complicated by the fact that there are two "Help" buttons in the application with the same class. Here is a picture of the application window I am trying to get handles for with the help button I want to click highlighted with a red box.2

I tried adding on the instance number which I obtained through AutoIT Info.

IntPtr button = FindWindowEx(hWndParent, IntPtr.Zero, "WindowsForms10.BUTTON.app.0.2c040a7_r9_ad113", "Help");

This also returned a 0 for button, as did replacing "Help" with null. If anyone is familiar with getting handles from Windows 10 Forms and knows how to do this, your help would be much appreciated. Thanks!

Andrew


Solution

  • Thanks to Hans for his post - it pointed me in the right direction. I've gone with using Selenium and Appium to automate clicks/input. For anyone that stumbles across this in future looking for a solution, here is some code to help.

    // You will need a few resources
    
    using System;
    using System.Windows.Forms;
    using OpenQA.Selenium.Appium.Windows;
    using OpenQA.Selenium.Remote;
    
    // Making our driver
    
    protected static WindowsDriver<WindowsElement> driver;
    
    // I don't want to have to manually open WinAppDriver so..
    
    System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
    pProcess.StartInfo.FileName = @"C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe";
    pProcess.StartInfo.Arguments = "olaa"; //argument
    pProcess.StartInfo.UseShellExecute = false;
    pProcess.StartInfo.RedirectStandardOutput = true;
    pProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
    pProcess.StartInfo.CreateNoWindow = true; //not diplay a windows
    pProcess.Start();
    string output = pProcess.StandardOutput.ReadToEnd(); //The output result
    pProcess.WaitForExit();
    
    // Now I connect to my app by setting up the driver
    
    DesiredCapabilities caps = new DesiredCapabilities();
    caps.SetCapability("platformName", "Windows");
    caps.SetCapability("platformVersion", "10");
    caps.SetCapability("deviceName", "WindowsPC");
    caps.SetCapability("app", "C:\\FileLocation.exe");
    driver = new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), caps);
    
    // Commands can be sent as below
    
    driver.FindElementByAccessibilityId("I'll explain this below").Click();
    

    To find the AccessibilityId, I found the easiest tool to use was AutoIT Window Info. Drag the finder over your desired button. Then in the summary tab your AccessibilityId is labeled simply as "ID". I went with AccessibilityId because I have multiple buttons with the same name in the app I wanted to control.

    You will need to have WinAppDriver installed and put the proper location into the code. Appium and Selenium can be added through the Nuget Manager but a few of the functions used in my code are depricated. I just went with the 3.0.1 versions of Selenium.WebDriver and Selenium.Support and the 3.0.0.1 version of Appium.WebDriver (others may work, these were just the first to work).