SeleniumHQ / selenium

A browser automation framework and ecosystem.
https://selenium.dev
Apache License 2.0
29.76k stars 8.02k forks source link

[🐛 Bug]: NoSuchDriverException for Windows app execution aliases #14088

Closed vlad8x8 closed 1 week ago

vlad8x8 commented 4 weeks ago

What happened?

The default way to run MS Teams desktop client (which is MSEdge-based app) is a Windows app execution aliass located at UserFolder\AppData\Local\Microsoft\WindowsApps\ms-teams.exe) Selenium Manager is failing on this file. The issue started on Selenium 4.20 because of https://github.com/SeleniumHQ/selenium/blob/4ecc1033caa9995427c25d36befb70b8faae96d7/java/src/org/openqa/selenium/internal/Require.java No issue with Selenium 4.19

org.openqa.selenium.internal.Require.FileStateChecker#isFile throws errors for Windows app execution aliases

How can we reproduce the issue?

https://github.com/vlad-velichko/selenium-bug-14088

Relevant log output

org.openqa.selenium.remote.NoSuchDriverException: Unable to obtain: msedgedriver, error MicrosoftEdge must exist: C:\Users\me\AppData\Local\Microsoft\WindowsApps\ms-teams.exe
For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location/
Build info: version: '4.21.0', revision: '79ed462ef4'
System info: os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '21-ea'
Driver info: driver.version: SelenideDriver

    at org.openqa.selenium.remote.service.DriverFinder.getBinaryPaths(DriverFinder.java:121)
    at org.openqa.selenium.remote.service.DriverFinder.getDriverPath(DriverFinder.java:55)
    at org.openqa.selenium.edge.EdgeDriver.generateExecutor(EdgeDriver.java:71)
    at org.openqa.selenium.edge.EdgeDriver.<init>(EdgeDriver.java:60)
    at org.openqa.selenium.edge.EdgeDriver.<init>(EdgeDriver.java:56)

Workaround

Get the app execution alias link from Windows registry

Operating System

Windows 10

Selenium version

Java 4.21.0

What are the browser(s) and version(s) where you see this issue?

MS Teams based on MS Edge based on Chrome 125

What are the browser driver(s) and version(s) where you see this issue?

msedgedriver 125.0.2535.85

github-actions[bot] commented 4 weeks ago

@vlad8x8, thank you for creating this issue. We will troubleshoot it as soon as we can.


Info for maintainers

Triage this issue by using labels.

If information is missing, add a helpful comment and then I-issue-template label.

If the issue is a question, add the I-question label.

If the issue is valid but there is no time to troubleshoot it, consider adding the help wanted label.

If the issue requires changes or fixes from an external project (e.g., ChromeDriver, GeckoDriver, MSEdgeDriver, W3C), add the applicable G-* label, and it will provide the correct link and auto-close the issue.

After troubleshooting the issue, please add the R-awaiting answer label.

Thank you!

github-actions[bot] commented 3 weeks ago

We need more information about this issue in order to troubleshoot.

Please turn on logging and re-run your code. Information on how to adjust logs for your language can be found in our Troubleshooting documentation.

vlad8x8 commented 3 weeks ago

added link to the repo with a project to reproduce the issue

vlad8x8 commented 2 weeks ago

@titusfortner is there a chance to remove file checks added in https://github.com/SeleniumHQ/selenium/blob/4ecc1033caa9995427c25d36befb70b8faae96d7/java/src/org/openqa/selenium/internal/Require.java#L265 for browser path? What is the reason for those checks?

titusfortner commented 2 weeks ago

We check the validity of the output so that we can provide better error messaging about why things aren't working. I see that Windows aliases do not like this code. The right answer I believe is to also check for Files.isSymbolicLink(file.toPath(). Would you be interested in making a PR for it?

vlad8x8 commented 2 weeks ago

@titusfortner After exploring this I realized, that this is not a symbolic link, it's an app execution alias. I can try to add a method isAppExecutionAlias(), but not sure if it won't fail on some non-Windows systems.

vlad8x8 commented 2 weeks ago

the method can be like this:

boolean isAppExecutionAlias() {
    final int WINDOWS_FILE_ATTRIBUTE_REPARSE_POINT = 0x400;
    if (FileSystems.getDefault().supportedFileAttributeViews().contains("dos")) {
        int fileAttrs = (int) Files.getAttribute(path, "dos:attributes", LinkOption.NOFOLLOW_LINKS);
        return (fileAttrs & WINDOWS_FILE_ATTRIBUTE_REPARSE_POINT) != 0;
    }
}

can I add it to Require.java or there is a better place?

titusfortner commented 2 weeks ago

Wow, that gets ugly. Please PR it to Require so we can check as part of isFile, we can discuss (with the more Java experts on the team) if this is the best way to do it.

Thank you!

joerg1985 commented 1 week ago

This has been fixed in 2a7ddf1fdeb724bb5f4bd6cd64867894aa485add by checking the executable state using the newer java.nio methods. I have deprecated the java.io stuff, so this can be removed in the future, if everything is working as expected.

vlad8x8 commented 1 week ago

@joerg1985 your commit doesn't use java.nio.file.LinkOption.NOFOLLOW_LINKS which is critical

are you guys pushing to master? omg

joerg1985 commented 1 week ago

@vlad8x8 i have missed to update the existence check, i did not expect this to fail in this case. I am using Files.notExists now to avoid a broken symlink to pass the check.

Small and limited changes are happening on trunk, bigger / complex in PRs.