WinAppDriver
WinAppDriver copied to clipboard
Appium Dotnet 5.0.0-beta01: Cannot instantiate WIndowsDriver: AppiumOptions "Vendor Prefix" causing driver instantiation error
I was trying out the Appium 5.0.0 Beta01. My capabilities/options looked like this:
var options = new AppiumOptions();
options.AddAdditionalCapability("app", "root");
options.AddAdditionalCapability("ms:experimental-webdriver", true);
WindowsDriver driver = new WindowsDriver(new Uri(WinAppDriverUrl), options, TimeSpan.FromSeconds(60));
but this set of options, specifically the option for ("app", "root), threw this error:
There is already an option for the appium:app capability. Please use the Application property instead. Parameter name: capabilityName
so I replaced it with this property instead:
options.App = "root";
which apparently passes the capability as ("appiumoption:app","root") instead of the old ("app", "root") key-value pair.
and so now I get this errorr:
OpenQA.Selenium.WebDriverArgumentException: Bad capabilities. Specify either app or appTopLevelWindow to create a session
I looked into the Appium dotnet source code and looks like the AppiumOptions class's method to create a new AppiumOption has been modified: AppiumOptions.cs diff: Appium 4.3.1 vs 5.0.0 Beta01 This method in particular seems to have brought the change, adding a vendor prefix before any and all additional options/capabilities:
public void AddAdditionalAppiumOption(string optionName, object optionValue)
{
string name = optionName.Contains(":") ? optionName : $"{VendorPrefix}:{optionName}";
this.ValidateCapabilityName(name);
this.additionalAppiumOptions[name] = optionValue;
}
I couldn't find any way to get around it. Here's a ticket for this issue in the Appium Dotnet Repo: https://github.com/appium/appium-dotnet-driver/issues/487
@kat-y @DHowett Is this being taken care of for the next release? This is a blocker on the upgrade path to Selenium 4 and Appium 5.
This works
var desktopCapabilities = new AppiumOptions();
desktopCapabilities.App = "Root";
string WindowsApplicationDriverUrl = "http://127.0.0.1:4725/wd/hub";
desktopSession = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), desktopCapabilities);
Assert.IsNotNull(desktopSession);
var RSWindow = desktopSession.FindElementByName("");
var RSTopLevelWindowHandle = RSWindow.GetAttribute("NativeWindowHandle");
RSTopLevelWindowHandle = (int.Parse(RSTopLevelWindowHandle)).ToString("x");
var appcapabilities = new AppiumOptions();
appcapabilities.AddAdditionalAppiumOption("appTopLevelWindow", RSTopLevelWindowHandle);
appcapabilities.AddAdditionalAppiumOption("newCommandTimeout", 300);
driver = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appcapabilities, TimeSpan.FromSeconds(50));
Hi @anunay1 thanks for the help but if you see my post, I mention using the dektopCapabilities.App = "Root" and still getting that error. So your code doesn't work either. What's your Appium Nuget package version?
The same that you are using, can you share the code
The "WindowsElement" class is deprecated in Appium 5 beta
How were you able to run this line of code? with the WindowsDriver<WindowsElement>
? Can you double check that your Nuget Appium package version is not 4.3.1?
desktopSession = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), desktopCapabilities);
I've posted my code in the original post, that's pretty much it, I'm trying to grab hold of the 'root' app in the desktop
oh my bad I am using 5.0.0-alpha appium version.
Hi @anunay1 were you able to make it run with appium 5.0.0-beta01?
No I have not tried.
@pradeipp I am able to make it work with the below code with notepad application with appium 5.0.0-beta01
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Windows;
using System;
using System.Diagnostics;
using System.Threading;
using OpenQA.Selenium.Appium.ImageComparison;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium;
namespace POCAppium5beta
{
[TestClass]
public class UnitTest1
{
private WindowsDriver desktopSession;
private WindowsDriver driver;
private WindowsDriver driver1;
private WindowsDriver desktopSession2;
[TestMethod]
public void TestMethod1()
{
string mainWindowTitle = "";
var allProcesses1 = Process.GetProcesses();
foreach (Process process in allProcesses1)
{
if (process.ProcessName.Contains("notepad"))
{
mainWindowTitle = process.MainWindowTitle;
}
}
var desktopCapabilities = new AppiumOptions();
desktopCapabilities.App = "Root";
string WindowsApplicationDriverUrl = "http://127.0.0.1:4725/wd/hub";
desktopSession = new WindowsDriver(new Uri(WindowsApplicationDriverUrl), desktopCapabilities);
Assert.IsNotNull(desktopSession);
var RSWindow = desktopSession.FindElement(MobileBy.Name(mainWindowTitle));
var RSTopLevelWindowHandle = RSWindow.GetAttribute("NativeWindowHandle");
RSTopLevelWindowHandle = (int.Parse(RSTopLevelWindowHandle)).ToString("x");
var appcapabilities = new AppiumOptions();
appcapabilities.AddAdditionalAppiumOption("appTopLevelWindow", RSTopLevelWindowHandle);
appcapabilities.AddAdditionalAppiumOption("newCommandTimeout", 300);
driver = new WindowsDriver(new Uri(WindowsApplicationDriverUrl), appcapabilities, TimeSpan.FromSeconds(50));
driver.FindElement(MobileBy.Name("Text Editor")).SendKeys("Hello there");
and if you want to launch the app you can use the below code:
var desktopCapabilities = new AppiumOptions();
desktopCapabilities.App = @"Your app";
string WindowsApplicationDriverUrl = "http://127.0.0.1:4725/wd/hub";
desktopSession = new WindowsDriver(new Uri(WindowsApplicationDriverUrl), desktopCapabilities);
Assert.IsNotNull(desktopSession);
desktopSession.FindElement(MobileBy.Name("your control")).Click();
I still get the same error. What version of winappdriver server are you using? @anunay1 I'm using the latest version, the release candidate rather than the stable release maybe that's impacting it?
I am not using winappdriverserver, I am using Appium server, that is evident from the code I shared:
string WindowsApplicationDriverUrl = "http://127.0.0.1:4725/wd/hub";
@kat-y This needs to be taken on priority, if not we will be stuck with the older versions of appium.
@pradeipp Did you managed to get it working?
@anunay1 No I haven't been able to make it work with WAD server. i'm thinking of trying the appium server soon but idk the risks involved in that. Does it work exactly like the WAD server? or are there any limitations I should be aware of ?
No it works exactly like the winappdriverserver. WAD will not work with the latest version of appium client.
Hi all, I am stuck as well. My test stopped working previous week on this error:
System.TypeLoadException : Access is denied: 'OpenQA.Selenium.Remote.DesiredCapabilities'.
So I have started to solve it, I have tried perhaps all possibility combinations:
- Update Appium.WebDriver (Nuget package in C# project) from 4.3.1 to 5.0b
- there were described problem above ("Bad capabilities. Specify either app or appTopLevelWindow to create a session")
- Downgrade Appium.WebDriver into lower version (e.g. 4.0) with Selenium 3.141
- there were problem, that Appium still uses 4.x Selenium version, probably due to another project in Solution, which uses higher Selenium
- Link Appium.WebDriver as a standalone project into Solution without Nuget
- the same problem, higher Selenium has been used
- Remove Nuget of Appium.WebDriver and starting own Appium server as described above (http://127.0.0.1:4725/wd/hub)
- problem with starting of application and WinAppDriver has been solved
- but there were new problem, Finding elements stop working and new one (MobileBy.Name) works only for Notepad example, but not for my application
@cernyjan I had the same. So, I set Selenium packages to the default version of 3.141 in common library and overridden them for another project. With this trick it works
@yevheniia-alikberova In the end this solution does not fit to us. We have to use higher version of Selenium in other projects due to found vulnerability in that by audit.
On the bright side we got an update from the Dev of this project @DHowett -
https://github.com/microsoft/WinAppDriver/issues/1704#issuecomment-1105500720
Looks like there's a prototype for W3C-style WinAppDriver server in progress and the next release(or the one after that) will hopefully resolve this issue. Fingers crossed.
Morning, not sure if this requires a separate ticket but based on the new AddAdditionalAppiumOption method we're having issues authenticating with BrowserStack for out mobile testing. The new method creates a json which looks like the below: { "appium:PlatformName": "Android", "appium:DeviceName": "Samsung Galaxy S20", "appium:PlatformVersion": "10.0", "appium:BrowserName": "Chrome", "appium:AutomationName": "UiAutomator2", "appium:browserstack.user": "username", "appium:browserstack.key": "password" }
And that throws an authentication error when creating the driver because it appears BrowserStack doesn't recognize the properties any more. With the previous AddAdditionalCapability method the json object was created like this: { "platformName": "Android", "deviceName": "Samsung Galaxy S20", "platformVersion": "10.0", "browserName": "Chrome", "automationName": "UiAutomator2", "browserstack.user": "username", "browserstack.key": "password" }
Any ideas how to pass those properties as before with the new method?
In case this helps anyone.
Nuget dependency of Appium.WebDriver 5.0.0-beta01 and appium installed ( npm install -g appium )
using NUnit.Framework;
using OpenQA.Selenium.Appium.Windows;
using System;
using System.Diagnostics;
using System.Linq;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium;
namespace TestProject
{
public class Example: AppiumWindowsDriverTestsBase
{
[Test]
public void Usage()
{
var driver = Appium.CreateWindowsDriverFromMainWindowTitle("Your_Main_Window_Title");
var found = driver.FindElement(ByWindowsAutomation.AccessibilityId("textAutomationId"));
}
}
public abstract class AppiumWindowsDriverTestsBase
{
private Process appiumProcess;
[SetUp]
public void Setup()
{
Appium.StartWinAppDriver();
appiumProcess = Appium.Start();
}
[TearDown]
public void TearDown()
{
appiumProcess.CloseMainWindow();
}
}
public static class ProcessHandleHelper
{
public static AppiumOptions AddTopLevelWindow(this AppiumOptions appiumOptions, string topLevelWindowHandle)
{
appiumOptions.AddAdditionalAppiumOption("appTopLevelWindow", topLevelWindowHandle);
return appiumOptions;
}
public static AppiumOptions AddTopLevelWindowFromMainWindowTitle(
this AppiumOptions appiumOptions,
string mainWindowTitle
) => appiumOptions.AddTopLevelWindow(FindProcessHandleByMainWindowTitle(mainWindowTitle));
public static string FindProcessHandleByMainWindowTitle(string mainWindowTitle) =>
FindProcessBy(process => process.MainWindowTitle == mainWindowTitle);
public static string FindProcessBy(Func<Process, bool> predicate)
{
var matchingProcess = Process.GetProcesses().First(predicate);
return matchingProcess.MainWindowHandle.ToString("x");
}
}
public class Appium
{
public const string Uri = "http://127.0.0.1:4723/wd/hub";
private const string DefaultX86Path = @"C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe";
public static Process Start() => Process.Start("appium");
public static void StartWinAppDriver(string path = DefaultX86Path) => Process.Start(path, Uri);
public static WindowsDriver CreateWindowsDriver(AppiumOptions appiumOptions) =>
new WindowsDriver(new Uri(Uri), appiumOptions);
public static WindowsDriver CreateWindowsDriverFromMainWindowTitle(string mainWindowTitle, AppiumOptions appiumOptions = null)
{
appiumOptions = appiumOptions ?? new AppiumOptions();
appiumOptions.AddTopLevelWindowFromMainWindowTitle(mainWindowTitle);
return Appium.CreateWindowsDriver(appiumOptions);
}
}
}
@pradeipp , did you get your issue resolved? I am using VS 2022 Pro and new to Appium/WinAppDriver. I am following a tutorial on launching notepad.exe using WinAppDriver. This line of code fails:
Can you please help?