Open anunayaabb opened 6 years ago
Hi @anunayaabb,
Thanks for the change proposal. To be clear, this proposal is to enable specifying a delay in the startup as @CryilJ suggested in issue #244, isn't it? In such scenario Windows Application Driver would wait for the specified duration after launching the application before attempting to locate the main application window.
This change proposal makes total sense and will very likely benefit many applications that require more time to start. Thus, we have marked this as an enhancement. For the time being, can you try attaching to already opened application window mechanism?
In this workaround, you should not need to re-launch the app after the failed session creation (that actually launched the application but failed to locate the window). Your session creation will then look like:
app
identifier (App will launch but session is not created since it can't find the application window in time)DesktopSession
to locate the main application window elementNativeWindowHandle
attribute to start a new session as shown in the example below.
https://github.com/Microsoft/WinAppDriver/tree/v1.0#attaching-to-an-existing-app-window@timotiusmargo Thanks,I tried it already it works, but that does not solve my issue and my UWP app does not support multiple instances. So if I switch to an existing window, the app crashes.
@timotiusmargo Below is the code snippet which I have implemented for my testing.Please do let me know if I am doing anything wrong.
try
{
session = new WindowsDriver
catch (Exception Ex)
{
if (Ex.Message.Contains("Failed to locate opened application window with appId: XXXXX_xygkxtyvxheec!App"))
{
Thread.Sleep(10000);
DesiredCapabilities desktopCapabilities = new DesiredCapabilities();
desktopCapabilities.SetCapability("app", "Root");
desktopSession = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), desktopCapabilities);
Assert.IsNotNull(desktopSession);
WindowsElement XXXShellWindow = desktopSession.FindElementByName("XXX");
string XXXShellTopLevelWindowHandle = (int.Parse(XXXShellWindow.GetAttribute("NativeWindowHandle"))).ToString("x");
appCapabilities.SetCapability("appToplevelWindow", XXXShellTopLevelWindowHandle);
session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities, TimeSpan.FromSeconds(20));
Assert.IsNotNull(session);
}
else
{
Assert.Fail("Unexpected error occured: {0}", Ex.Message);
}
Can you please let me know any tentative date for implementation of this enhancement. I will be of great help even if you can share and exe with only this fix(or a daily build in case if it is there )
Hi @anunayaabb,
I don't have any tentative date at the moment and we can get back to you when we do. For the time being, the given workaround should work fine.
The code snippet you pasted above looks fine to me. At what point did your application crash? Can you include the HTTP request command logs that you find in WinAppDriver.exe
console? There's no code above that re-launch the application or requiring it to support multi instance. So the fact that your application doesn't support multi instance should not be the cause of the crash.
Hi @timotiusmargo :please find the http server logs: C:\Automation\WindowsApplicationDriver>WinAppDriver.exe 192.168.125.204 4725 Windows Application Driver listening for requests at: http://192.168.125.204:4725/ Press ENTER to exit.
========================================== POST /session HTTP/1.1 Accept: application/json, image/png Connection: Keep-Alive Content-Length: 125 Content-Type: application/json;charset=utf-8 Host: 192.168.125.204:4725
HTTP/1.1 500 Internal Error Content-Length: 177 Content-Type: application/json
{"status":13,"value":{"error":"unknown error","message":"Failed to locate opened application window with appId: XXX_xygkxtyvxheec!App, and processId: 2900"}}
========================================== POST /session HTTP/1.1 Accept: application/json, image/png Content-Length: 63 Content-Type: application/json;charset=utf-8 Host: 192.168.125.204:4725
HTTP/1.1 200 OK Content-Length: 111 Content-Type: application/json
{"sessionId":"33CC4C55-6245-4B4D-B8F0-8C356852C64A","status":0,"value":{"app":"Root","platformName":"Windows"}}
========================================== POST /session/33CC4C55-6245-4B4D-B8F0-8C356852C64A/element HTTP/1.1 Accept: application/json, image/png Content-Length: 50 Content-Type: application/json;charset=utf-8 Host: 192.168.125.204:4725
HTTP/1.1 200 OK Content-Length: 95 Content-Type: application/json
{"sessionId":"33CC4C55-6245-4B4D-B8F0-8C356852C64A","status":0,"value":{"ELEMENT":"42.393694"}}
========================================== GET /session/33CC4C55-6245-4B4D-B8F0-8C356852C64A/element/42.393694/attribute/NativeWindowHandle HTTP/1.1 Accept: application/json, image/png Host: 192.168.125.204:4725
HTTP/1.1 200 OK Content-Length: 80 Content-Type: application/json
{"sessionId":"33CC4C55-6245-4B4D-B8F0-8C356852C64A","status":0,"value":"393694"}
========================================== POST /session HTTP/1.1 Accept: application/json, image/png Content-Length: 153 Content-Type: application/json;charset=utf-8 Host: 192.168.125.204:4725
HTTP/1.1 500 Internal Error Content-Length: 177 Content-Type: application/json
{"status":13,"value":{"error":"unknown error","message":"Failed to locate opened application window with appId: XXX_xygkxtyvxheec!App, and processId: 2900"}}
Any update on the implementation you can share.
Hi @anunayaabb,
The last session creation command below taken from the log above is where the problem lies:
==========================================
POST /session HTTP/1.1
Accept: application/json, image/png
Content-Length: 153
Content-Type: application/json;charset=utf-8
Host: 192.168.125.204:4725
HTTP/1.1 500 Internal Error
Content-Length: 177
Content-Type: application/json
{"status":13,"value":{"error":"unknown error","message":"Failed to locate opened application window with appId: XXX_xygkxtyvxheec!App, and processId: 2900"}}
This command is still trying to create a session by launching the app with the given XXX_xygkxtyvxheec!App
appId. At this point you should be creating the session using the given appTopLevelWindow
capability instead. This could be the reason why you see the application is being launched twice. Can you make sure that the new session is created from the appTopLevelWindow
by using a new DesiredCapabilities
instance as shown below?
// Create session by attaching to Cortana top level window
DesiredCapabilities appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability("appTopLevelWindow", CortanaTopLevelWindowHandle);
CortanaSession = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);
@timotiusmargo Thanks, I tried that and I am able to switch to the opened window, but after switching , my app crashes and that is an expected behaviour of my app.
Please dole me know by when will you be available with this implementation.
@timotiusmargo Any update on this issue.
Thanks @anunayaabb. We're looking into this.
Do we have any ETA for this issue
I am trying to inspect the Element in a desktop application. I am unable to inspect some of the elements. The desktop application is developed using VB. when i asked our developers they told some of the pages are jsp kind of pages which i am unable to inspect. I tried with inpect.exe and other tools also. Can anyone help me on this?
Any update on this issue? We are trying to test an app that takes like 6-7 seconds to open.
Hi @timotiusmargo, do you have any news about this issue?
Option 1: Your best bet, is that you are not waiting an implicit amount of seconds:
`DesiredCapabilities tempAppLauncherCapabilities = new DesiredCapabilities();
tempAppLauncherCapabilities.SetCapability("app", "AppName");
tempAppLauncherCapabilities.SetCapability("deviceName", "WindowsPC");
session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), tempAppLauncherCapabilities);
// This is what you want to do, wait FROM SECONDS, not minutes or anything else, I think there is a bug in the conversion of minutes to seconds, because waiting in minutes never works for me
**session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(600);`**
Option 2: just to explicitly throw a Thread.Sleep() method after you instantiate your session before you start searching for the elements. Just have it wait an arbitrary amount of seconds like 10 seconds in case if it takes longer than 6-7 seconds. For this, you are telling WinAppDriver "Hey, stop looking x amount of seconds," then WinAppDriver says, hey okay 👍!
`DesiredCapabilities tempAppLauncherCapabilities = new DesiredCapabilities();
tempAppLauncherCapabilities.SetCapability("app", "AppName");
tempAppLauncherCapabilities.SetCapability("deviceName", "WindowsPC");
session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), tempAppLauncherCapabilities);
session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(60);
// Put it right here! After you create your session, because at this moment, your application is launching, so telling WinAppDriver to wait is what is going on here
**System.Threading.Thread.Sleep(10000);**
Option 3: If you create a timer method that waits for the main screen to be in view, you're going to have a verbose method waiting like so:
[SetUp]
public static void SetUp()
{
// Instantiate the session here
// Then call the WaitForMainScreen() method which I have return the main screen element when searching for it and waiting for it to appear
Assert.IsNotNull(WaitForMainScreen());
}
// Wrapper for waiting for the main based on timeouts
private static readonly Stopwatch timer = new Stopwatch();
private static int waitTime = 60000;
public static WindowsElement WaitForMainScreen()
{
Stopwatch timer = new Stopwatch();
int waitTime = 60000;
bool isElementVisible = false;
WindowsElement element = null;
timer.Start();
while (timer.Elapsed <= TimeSpan.FromMilliseconds(waitTime) && isElementVisible == false)
{
try
{
element = session.FindElement(identifier);
if (element == session.FindElement(identifier))
{
isElementVisible = true;
}
}
catch
{
continue;
}
}
timer.Stop();
Assert.IsFalse(timer.Elapsed > TimeSpan.FromMilliseconds(waitTime), "Timeout Elapsed, element with accessibility of | " + identifier + " | not found.");
return element;
}
The APP which I am testing takes at least 7 to 8 sec to launch the Main Window, because of which the test fails , I can switch to the opened window but that will only be possible if the app supports multiple instances, if the app supports only one instance, the app will crash (that is what happens in my case), and that seems like a real bottle neck in automation for those apps.