Any findelements method raises a timeout exception
Hello,
I only recently started using WinAppDriver to automate a WPF application. I am connecting to an already running application and then trying to iterate over all its controls, recursively. But, for some reason, I didn't manage to use any type of FindElements (ByClassName, ByAccessibilityId, ByName etc.) - using these type of methods ALWAYS raises a timeout exception as follows:
Test method UnitTestProject1.UnitTest1.TestMethod1 threw exception:
OpenQA.Selenium.WebDriverException: The HTTP request to the remote WebDriver server for URL http://127.0.0.1:4723/session/3B3ABB59-3B54-49AD-8E1C-2BD3A1CEE7D5/elements timed out after 120 seconds. --->
System.Net.WebException: The request was aborted: The operation has timed out.
Stack Trace:
HttpWebRequest.GetResponse()
HttpCommandExecutor.MakeHttpRequest(HttpRequestInfo requestInfo)
--- End of inner exception stack trace ---
HttpCommandExecutor.MakeHttpRequest(HttpRequestInfo requestInfo)
HttpCommandExecutor.Execute(Command commandToExecute)
AppiumCommandExecutor.Execute(Command commandToExecute)
RemoteWebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
RemoteWebDriver.FindElements(String mechanism, String value)
AppiumDriver`1.FindElementsByXPath(String xpath)
UnitTest1.TestMethod1() line 80
This is how a snippet of my code looks like - which prints the ID of the first button, as expected.:
public void TestMethod1()
{
AppiumOptions desktopCapabilities = new AppiumOptions();
desktopCapabilities.AddAdditionalCapability("app", "Root");
desktopCapabilities.AddAdditionalCapability("platformName", "Windows");
desktopCapabilities.AddAdditionalCapability("deviceName", "WindowsPC");
WindowsDriver<WindowsElement> desktopSession = new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), desktopCapabilities, TimeSpan.FromMinutes(150));
var appWindow = desktopSession.FindElementByName("XXXXXXXXXXX");
var topLevelWindowHandle = appWindow.GetAttribute("NativeWindowHandle");
topLevelWindowHandle = int.Parse(topLevelWindowHandle).ToString("X");
AppiumOptions capabilities = new AppiumOptions();
capabilities.AddAdditionalCapability("deviceName", "WindowsPC");
capabilities.AddAdditionalCapability("appTopLevelWindow", topLevelWindowHandle);
desktopSession = new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), capabilities, TimeSpan.FromSeconds(120));
desktopSession.SwitchTo().Window(topLevelWindowHandle);
Console.WriteLine(desktopSession.FindElementByClassName("Button"));
}
This is how this button looks line in inspect.exe:
How found: Selected from tree... Name: "ID_ApplicationMenuButton" ControlType: UIA_ButtonControlTypeId (0xC350) LocalizedControlType: "button" BoundingRectangle: {l:1 t:37 r:57 b:62} IsEnabled: true IsOffscreen: false IsKeyboardFocusable: true HasKeyboardFocus: false AcceleratorKey: "" AccessKey: "" ProcessId: 14864 RuntimeId: [7.3A10.1077FBF] AutomationId: "ID_ApplicationMenuButton" FrameworkId: "WPF" ClassName: "Button" IsControlElement: true IsContentElement: true ProviderDescription: "[pid:14864,providerId:0x0 Main(parent link):Unidentified Provider (managed:MS.Internal.Automation.ElementProxy, PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)]" IsPassword: false ItemStatus: "" ItemType: "" IsRequiredForForm: false HelpText: "" ClickablePoint: {x:29 y:49} Orientation: 0 IsDialog: false HeadingLevel: HeadingLevel_None (0x138B2) LegacyIAccessible.ChildId: 0 LegacyIAccessible.DefaultAction: "Press" LegacyIAccessible.Description: "" LegacyIAccessible.Help: "" LegacyIAccessible.KeyboardShortcut: "" LegacyIAccessible.Name: "ID_ApplicationMenuButton" LegacyIAccessible.Role: push button (0x2B) LegacyIAccessible.State: focusable (0x100000) LegacyIAccessible.Value: "" Toggle.ToggleState: Off (0) IsAnnotationPatternAvailable: false IsDragPatternAvailable: false IsDockPatternAvailable: false IsDropTargetPatternAvailable: false IsExpandCollapsePatternAvailable: false IsGridItemPatternAvailable: false IsGridPatternAvailable: false IsInvokePatternAvailable: false IsItemContainerPatternAvailable: false IsLegacyIAccessiblePatternAvailable: true IsMultipleViewPatternAvailable: false IsObjectModelPatternAvailable: false IsRangeValuePatternAvailable: false IsScrollItemPatternAvailable: false IsScrollPatternAvailable: false IsSelectionItemPatternAvailable: false IsSelectionPatternAvailable: false IsSpreadsheetItemPatternAvailable: false IsSpreadsheetPatternAvailable: false IsStylesPatternAvailable: false IsSynchronizedInputPatternAvailable: true IsTableItemPatternAvailable: false IsTablePatternAvailable: false IsTextChildPatternAvailable: false IsTextEditPatternAvailable: false IsTextPatternAvailable: false IsTextPattern2Available: false IsTogglePatternAvailable: true IsTransformPatternAvailable: false IsTransform2PatternAvailable: false IsValuePatternAvailable: false IsVirtualizedItemPatternAvailable: false IsWindowPatternAvailable: false IsCustomNavigationPatternAvailable: false IsSelectionPattern2Available: false FirstChild: "" image LastChild: "File" text Next: "ID_MinimizeButton" button Previous: "Second_Modify" XXXXXXXXX Other Props: Object has no additional properties Children: "" image "" image "" image "" image "" image "File" text Ancestors: "XXXXXXXX" window "Desktop 1" pane [ No Parent ]
However, I would like to get all available buttons (there are 28 buttons at this application level) and while running FindElements (in plural, see below) I get the timeout exception mentioned above:
Console.WriteLine(desktopSession.FindElementsByClassName("Button"));
Any suggestion what am I doing wrong?
Search elements using such a common locator under all Desktop elements is not a good idea because there can be a lot of elements on the desktop. I suppose WinAppDriver can be not so performance proficient. Why is your search using a Desktop session?
Try:
- Use a more unique locator by specific app class or name
- Attach to your program by process or app name https://github.com/microsoft/WinAppDriver/issues/534#issuecomment-562030077
@Shakevg thank you for your prompt response. I updated my code using the link your shared and now I use it as follows:
public class UnitTest1
{
private const string WindowsDriverUri = "http://127.0.0.1:4723";
private static WindowsDriver<WindowsElement> CreateSessionForAlreadyRunningApp(string appText)
{
IntPtr appTopLevelWindowHandle = new IntPtr();
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.IndexOf(appText, StringComparison.OrdinalIgnoreCase) >= 0 ||
clsProcess.MainWindowTitle.IndexOf(appText, StringComparison.OrdinalIgnoreCase) >= 0)
{
appTopLevelWindowHandle = clsProcess.MainWindowHandle;
break;
}
}
var appTopLevelWindowHandleHex = appTopLevelWindowHandle.ToString("x"); //convert number to hex string
AppiumOptions appCapabilities = new AppiumOptions();
appCapabilities.AddAdditionalCapability("appTopLevelWindow", appTopLevelWindowHandleHex);
var appSession = new WindowsDriver<WindowsElement>(new Uri(WindowsDriverUri), appCapabilities);
return appSession;
}
[TestMethod]
public void TestMethod1()
{
var appSession = CreateSessionForAlreadyRunningApp("XXXXXXX"); // XXXXXXX = application name
Console.WriteLine((appSession.FindElementByAccessibilityId("Structure")); // ended successfully
Console.WriteLine((appSession.FindElementsByAccessibilityId("Structure")); // looking for elements raises a timeout exception
}
}
Still, using FindElements (in plural) raises a timeout exception (even if I extend the timeout to 120 seconds or more)
Attaching a screenshot from inspect.exe - the buttons in first level under application window are the ones I am trying to access.
What am I missing?
Are you using winappdriver.exe, there is an issue with the exe wherein the messages are not flushed and then raises this time out exception.
@anunay1 I do use winappdriver.exe (tried almost all versions available here. What is the alternative approach?
An alternative option would be to use appium.
Also when you get this exception try to get the page source.
@anunay1 I switched to Appium. Please confirm I did that correctly:
- I changed WindowsDriverUri variable from "http://127.0.0.1:4723" to "http://127.0.0.1:4723/wd/hub"
- I ran WinAppDriver.exe as follows - "winappdriver.exe 127.0.0.1 4723/wd/hub"
Still, same exception is raised after 60 seconds. I tried to catch this exception and print the page source as follows "Console.WriteLine(appSession.PageSource);" but this line also runs into timeout exception. Deadlock :(
You do not need to run winappdriver.exe. Just need to run appium server
@anunay1 Things are getting complex, though. Recall that I am running a Windows application test. I installed appium and ran it as follows: "Appium -a 127.0.0.1 -p 4723" I then received this error message:
OpenQA.Selenium.WebDriverException: 'automationName' can't be blank
so I added the following capability:
appCapabilities.AddAdditionalCapability("appium:automationName",AutomationName.Appium);
But then I get this error:
OpenQA.Selenium.WebDriverException: An unknown server-side error occurred while processing the command. Original error: Could not find a driver for automationName 'Appium' and platformName 'Windows'. Have you installed a driver that supports those capabilities? Run 'appium driver list --installed' to see. (Lower-level error: Could not find installed driver to support given caps)
I guess I am just doing it the wrong way.
Automation name is windows and also please do not install the latest version of appium,switch to 2.0 and below 3.
Now I run this code:
private const string WindowsDriverUri = "http://127.0.0.1:4723";
private static WindowsDriver<WindowsElement> CreateSessionForAlreadyRunningApp(string appText)
{
IntPtr appTopLevelWindowHandle = new IntPtr();
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.IndexOf(appText, StringComparison.OrdinalIgnoreCase) >= 0 ||
clsProcess.MainWindowTitle.IndexOf(appText, StringComparison.OrdinalIgnoreCase) >= 0)
{
appTopLevelWindowHandle = clsProcess.MainWindowHandle;
break;
}
}
var appTopLevelWindowHandleHex = appTopLevelWindowHandle.ToString("x"); //convert number to hex string
AppiumOptions appCapabilities = new AppiumOptions();
appCapabilities.AddAdditionalCapability("appTopLevelWindow", appTopLevelWindowHandleHex);
appCapabilities.AddAdditionalCapability("appium:automationName", "Windows");
var appSession = new WindowsDriver<WindowsElement>(new Uri(WindowsDriverUri), appCapabilities); //, TimeSpan.FromMinutes(60)
return appSession;
}
Installed:
install --source=npm appium-windows-driver
Ran appium version 2.0.1:
And get this exception in my Visual Studio:
Message:
Test method UnitTestProject1.UnitTest1.TestMethod1 threw exception:
OpenQA.Selenium.WebDriverException: An unknown server-side error occurred while processing the command. Original
error: WinAppDriver server is not listening within 10000ms timeout. Make sure it could be started manually
Stack Trace:
RemoteWebDriver.UnpackAndThrowOnError(Response errorResponse)
RemoteWebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
RemoteWebDriver.StartSession(ICapabilities desiredCapabilities)
RemoteWebDriver.ctor(ICommandExecutor commandExecutor, ICapabilities desiredCapabilities)
AppiumDriver`1.ctor(Uri remoteAddress, ICapabilities appiumOptions)
UnitTest1.CreateSessionForAlreadyRunningApp(String appText) line 52
UnitTest1.TestMethod1() line 70
Hello, based on the above correspondence, can someone suggest what am I still doing wrong and might cause this exception?
the same issue with appium and and winappdriver, could someone please take a look?