Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Appium WebDriverException: Failed to Locate Application Window for Custom Desktop App #2043

Open
ofriDev opened this issue Jan 6, 2025 · 10 comments

Comments

@ofriDev
Copy link

ofriDev commented Jan 6, 2025

I have a desktop application written in Flet Python, compiled to exe using pyinstaller.
I'm trying to add a CI/CD pipeline that will perform UI tests.
For this, I am using Appium and WinAppDriver over Python.

I did a test on Notepad — it works great.
When I try it on my application, it fails with the following error: selenium.common.exceptions.WebDriverException: Message: Failed to locate opened application window with appId: C:\Users\TEST\Desktop\EXE\dist\app\app.exe, and processId: 2904

The script manages to open the application, but still fails with this error.

The code base of the script from https://github.com/victorkipruto/desktop-automation/tree/master

Here is my main script code

from selenium.webdriver.common.keys import Keys

from src.automaton import webdriver
from src.automaton.options import DesktopOptions

caps = DesktopOptions()
caps.set_capability("app",r"C:\Users\TEST\Desktop\EXE\dist\app\app.exe")
caps.set_capability("automationName", "Windows")
caps.set_capability("newCommandTimeout", 60)
caps.set_capability("ms:waitForAppLaunch", "5")

driver = webdriver.Remote(
    command_executor='http://127.0.0.1:4723',
    options=caps
)
@anunay1
Copy link

anunay1 commented Jan 7, 2025

Does you application has a splash screen?

@ofriDev
Copy link
Author

ofriDev commented Jan 7, 2025

Does you application has a splash screen?

No.

For one app it takes a while to load (5 sec, and show a gray screen till full load).

But I checked this issue and I've done a light / skinny app with only some buttons and text fields, and it still crashed with the same error.

@Shakevg
Copy link

Shakevg commented Jan 8, 2025

@ofriDev Try this

@ofriDev
Copy link
Author

ofriDev commented Jan 9, 2025

@ofriDev Try this

It seems it works, but not connecting to my app.
for validate I'm trying to get all the elements in the app like so:

elem: WebElement = driver.find_element(AppiumBy.XPATH, "//*")
print(elem)

And I got dict[str, str]:
{'ELEMENT': '42.65552'}

This is not all my elements in the app (length wise) and I can't know what this element is because it is not indicative; it doesn't display the element's text.

My whole code:

from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.remote.webelement import WebElement

from src.automaton import webdriver
from src.automaton.options import DesktopOptions



try:
    caps = DesktopOptions()
    caps.set_capability("app", r"C:\Users\TEST\Desktop\EXE\dist\app\app.exe")
    caps.set_capability("automationName", "Windows")
    caps.set_capability("newCommandTimeout", 60)
    caps.set_capability("ms:waitForAppLaunch", "5")
    driver = webdriver.Remote(
        command_executor='http://127.0.0.1:4723',
        options=caps
    )
except Exception as e:
    caps = DesktopOptions()
    caps.set_capability("app", r"Root")
    caps.set_capability("automationName", "Windows")
    caps.set_capability("newCommandTimeout", 60)
    caps.set_capability("ms:waitForAppLaunch", "5")
    driver = webdriver.Remote(
        command_executor='http://127.0.0.1:4723',
        options=caps
    )


elem: WebElement = driver.find_element(AppiumBy.XPATH, "//*")
print(elem)

@Shakevg
Copy link

Shakevg commented Jan 9, 2025

In except try to connect to the existing app using process or Desktop session

@ofriDev
Copy link
Author

ofriDev commented Jan 12, 2025

In except try to connect to the existing app using process or Desktop session

It's still not solving the issue.
Getting the error:
selenium.common.exceptions.WebDriverException: Message: Bad capabilities. Specify either app or appTopLevelWindow to create a session
(In the except block)

It seems its getting the right handle, but not recognize it as appTopLevelWindow.

from appium.options.windows import WindowsOptions
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.remote.webelement import WebElement

from src.automaton import webdriver
from src.automaton.options import DesktopOptions
import win32gui

def find_window_handle():
    handleList = []
    def findit(hwnd,ctx):
        if win32gui.GetWindowText(hwnd) == "app": # check the title
            handleList.append(hwnd)

    win32gui.EnumWindows(findit,None)
    return handleList


try:
    caps = DesktopOptions()
    caps.set_capability("app", r"C:\Users\TEST\Desktop\EXE\dist\app\app.exe")
    caps.set_capability("automationName", "Windows")
    caps.set_capability("newCommandTimeout", 60)
    caps.set_capability("ms:waitForAppLaunch", "5")
    driver = webdriver.Remote(
        command_executor='http://127.0.0.1:4723',
        options=caps
    )
except Exception as e:
    handle = hex(find_window_handle()[0])
    print(handle)
    caps = DesktopOptions()
    caps.set_capability("automationName", "Windows")
    caps.set_capability("newCommandTimeout", 60)
    caps.set_capability("ms:waitForAppLaunch", "5")
    caps.set_capability("appTopLevelWindow", handle)
    driver = webdriver.Remote(
        command_executor='http://127.0.0.1:4723',
        options=caps
    )


elem: WebElement = driver.find_element(AppiumBy.XPATH, "//*")
print(elem)

@anunay1
Copy link

anunay1 commented Jan 13, 2025

it should be
elem: WebElement = driver.find_elements(AppiumBy.XPATH, "//*")
print(elem)

not
elem: WebElement = driver.find_element(AppiumBy.XPATH, "//*")
print(elem)

@ofriDev
Copy link
Author

ofriDev commented Jan 14, 2025

it should be elem: WebElement = driver.find_elements(AppiumBy.XPATH, "//*") print(elem)

not elem: WebElement = driver.find_element(AppiumBy.XPATH, "//*") print(elem)

This is a step ahead of the problem.
The problem is before this line. The script fails in the except block due to incorrect caps.
selenium.common.exceptions.WebDriverException: Message: Bad capabilities. Specify either app or appTopLevelWindow to create a session

Updated code:

from appium.options.windows import WindowsOptions
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.remote.webelement import WebElement

from src.automaton import webdriver
from src.automaton.options import DesktopOptions
import win32gui

def find_window_handle():
    handleList = []
    def findit(hwnd,ctx):
        if win32gui.GetWindowText(hwnd) == "app": # check the title
            handleList.append(hwnd)

    win32gui.EnumWindows(findit,None)
    return handleList


try:
    caps = DesktopOptions()
    caps.set_capability("app", r"C:\Users\TEST\Desktop\EXE\dist\app\app.exe")
    caps.set_capability("automationName", "Windows")
    caps.set_capability("newCommandTimeout", 60)
    caps.set_capability("ms:waitForAppLaunch", "5")
    driver = webdriver.Remote(
        command_executor='http://127.0.0.1:4723',
        options=caps
    )
except Exception as e:
    handle = hex(find_window_handle()[0])
    print(handle)
    caps = DesktopOptions()
    caps.set_capability("automationName", "Windows")
    caps.set_capability("newCommandTimeout", 60)
    caps.set_capability("ms:waitForAppLaunch", "5")
    caps.set_capability("appTopLevelWindow", handle)
    driver = webdriver.Remote(
        command_executor='http://127.0.0.1:4723',
        options=caps
    )


elem: list[WebElement] = driver.find_elements(AppiumBy.XPATH, "//*")
print(elem)

@anunay1
Copy link

anunay1 commented Jan 14, 2025

oh ok. Are you using selenium 4? selenium 4 is not supported yet. Need to move to 3.

@ofriDev
Copy link
Author

ofriDev commented Jan 16, 2025

oh ok. Are you using selenium 4? selenium 4 is not supported yet. Need to move to 3.

I see.
Unfortunately Now it's not working at all.
I downgraded to Selenium-3.141.0 & Appium-Python-Client-1.3.0 & Updated the code for these versions, and now it doesn't even open the app and gives no response in the driver.

Exception:
ValueError: Timeout value connect was <object object at 0x0000025315308660>, but it must be an int, float or None.

My updated code:

from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webelement import WebElement
import win32gui


def find_window_handle():
    handleList = []
    def findit(hwnd, ctx):
        if win32gui.GetWindowText(hwnd) == "app":  # check the title
            handleList.append(hwnd)

    win32gui.EnumWindows(findit, None)
    return handleList


try:
    # Set capabilities directly using DesiredCapabilities
    caps = {
        "app": r"C:\Users\TEST\Desktop\EXE\dist\app\app.exe",
        "automationName": "Windows",
        "newCommandTimeout": 60,
        "ms:waitForAppLaunch": "5",
    }

    # Initialize the Appium driver using the defined capabilities
    driver = webdriver.Remote(
        command_executor='http://127.0.0.1:4723/wd/hub',  # Tried also http://127.0.0.1:4723/
        desired_capabilities=caps
    )
except Exception as e:
    # If initialization fails, find the window handle and retry with appTopLevelWindow capability
    handles = find_window_handle()
    if len(handles) == 0:
        raise Exception("Program not found")

    handle = hex(find_window_handle()[0])
    print(handle)

    # Set capabilities directly using DesiredCapabilities
    caps = {
        "appTopLevelWindow": handle,
        "automationName": "Windows",
        "newCommandTimeout": 60,
        "ms:waitForAppLaunch": "5",
    }

    driver = webdriver.Remote(
        command_executor='http://127.0.0.1:4723/wd/hub',  # Tried also http://127.0.0.1:4723/
        desired_capabilities=caps
    )

# Find elements using By.XPATH and print them
elem: list[WebElement] = driver.find_elements(By.XPATH, "//*")
print(elem)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants