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
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).