MicrosoftEdge / WebView2Feedback

Feedback and discussions about Microsoft Edge WebView2
https://aka.ms/webview2
452 stars 55 forks source link

Transient NuGet Reference for Microsoft.Web.WebView2 does not install /runtimes Folder #3432

Closed RickStrahl closed 1 year ago

RickStrahl commented 1 year ago

Renamed the title of this topic after exploration. Below comment has isolated the problem originally stated to the /runtimes folder not getting deployed from a Transient NuGet package - only from a direct project reference.

I've been dealing with a number of users complaining about WebView Runtime failures during start up of my application.

There are a number of reports that tell me that the application starts and then fails to detect the WebView Runtime is installed which I check for with:

// If version no lookup or parsing fails WebView is not available
versionNo = CoreWebView2Environment.GetAvailableBrowserVersionString();

I call this code during startup of the application and the exception block around it captures the failure and if this fails the assumption is that the Runtime is not installed. Additionally I also check for a Runtime version higher than the .NET version, but on failure that code never gets hit:

        public static bool IsWebViewVersionInstalledUi(bool showDownloadUi = false)
        {
            string versionNo = null;
            Version asmVersion = null;
            Version ver = null;

            try
            {
                // If version no lookup or parsing fails WebView is not available
                versionNo = CoreWebView2Environment.GetAvailableBrowserVersionString();

                // strip off 'canary' or 'stable' version
                versionNo = versionNo.ExtractString("", " ", allowMissingEndDelimiter: true)?.Trim();
                ver = new Version(versionNo);

                if (!mmApp.Configuration.System.IgnoreWebViewVersionMismatch)
                {
                    asmVersion = typeof(CoreWebView2Environment).Assembly.GetName().Version;
                    if (ver.Build >= asmVersion.Build)
                        return true;
                }
                else
                {
                    return true;
                }

                return true;
            }
            catch(Exception ex) 
            {
                mmApp.Log("WebView Version lookup failed.", ex.GetBaseException(), logLevel: LogLevels.Error);
            }

            if (!showDownloadUi)
                return false;

            // ... UI display
           return false;
} 

Until recently I haven't had any reports of issues. However, in the last couple of weeks there have been quite a few reports that mention that the WebView Runtime not installed notification is popping up.

The runtime installer will hang or outright fail. This is a WPF app so the check is called from App.xaml.cs and the OnStartup handler. I have never seen this fails for me, but I see occasional mentions of this failure.

My question is Why would CoreWebView2Environment.GetAvailableBrowserVersionString() ever fail assuming the WebView is installed?

User claim they have the latest WebView installed, and when cheking their version in Installed Apps tend to have the latest version and they can't uninstall it to force a complete reinstall (no options to uninstall, only repair/modify):

image

This seems to suggest this is a system installed version. Did Windows 11 start auto-installing the runtime? If so is there some documentation at which version this started? And - can the OS Installed version even be updated?

From what I can tell it looks like my application running the WebView Runtime Installer when the WebView Runtime is system installed seems to perhaps corrupt the installed runtime?

FWIW I had an earlier issue where I asked to not always install the WebView Runtime when that Runtime version is already installed. However, the MicrosoftEdgeWebview2Setup.exe seems to run a full runtime download and install regardless of whether the that version of the Runtime is already installed.

WebView Version: 112.0.1722.58
.NET Component: 112.0.1722.45

AB#44326557

novac42 commented 1 year ago

Thanks for reaching out. I've assigned this to a dev that can follow up on this.

LiangTheDev commented 1 year ago

Windows 11 has WebView2 Runtime installed and auto updated from day one. And we started to push WebView2 Runtime to Windows 10 machines last year and completed in February this year.

There are 2 possible reasons for GetAvailableBrowserVersionString to fail even though the runtime is shown as installed:

We would have to collect logs to know what's going on. procmon log should tell us which file/registry we tried to access before failing the API call. If it is feasible to collect procmon log, Edge installer logs (https://github.com/MicrosoftEdge/WebView2Feedback/blob/main/diagnostics/install.md) would also help a lot.

RickStrahl commented 1 year ago

I have some more information on the issue.

I'm running .NET 472 and I think the issue is related to the Build Targeting in the project.

When I build with CpuAny I get the above failure. The Webview seems to not work at all as all CoreWebView2 calls fail.

When I explicitly target x64 everything is fine.

However, I double checked when running with the CpuAny build and the actual app starts up as 64 bit also (it's not showing as 32 bit), so not sure what's different unless the WebView component somehow checks for explicit targets to bind to?

To make this even more confusing - when running inside of the VS Debugger AnyCpu works. Running the compiled EXE doesn't.

LiangTheDev commented 1 year ago

I've created an internal tracking work item for this AnyCpu issue. Could you please try explicitly specifying where to find WebView2Loader.dll using CoreWebView2Environment.SetLoaderDllFolderPath, and see whether that makes a difference?

RickStrahl commented 1 year ago

So I set up a very simple test project to try to duplicate this, but for the simple project this seems to work just fine. Using AnyCpu works no problem. However on my actual live project switching between the x64 and AnyCpu results in any call to CoreWebView2 APIs to fail (and the main controls won't render).

I'll keep digging a bit later and see if I can find what else might be triggering this. I double checked just now though - when failing with AnyCpu the app definitely shows as running 64 bit in Process Explorer, so it's not a 32 bit issue (although that would make sense).

This is more a curious issue than anything as I can (and have been actually) run in x64 and that works and fixes my immediate issue.

RickStrahl commented 1 year ago

Could you please try explicitly specifying where to find WebView2Loader.dll using CoreWebView2Environment.SetLoaderDllFolderPath, and see whether that makes a difference?

I'm not specifying a dll folder explicitly so it's using the default folder. Where is that folder by default? Or can I check to see what it's pointing to?

LiangTheDev commented 1 year ago

The default is supposed to be x64/x86/arm64 sub folder of the folder where the app's exe is.

RickStrahl commented 1 year ago

Ok so I can confirm the following in my main application:

So I think the issue is the missing runtimes folder. In the Markdown Monster project the runtimes folder is not set. The difference is that in that project the Microsoft.Web.WebView2 package is a transient from another project Westwind.WebView.

Below are compiles of both my simple test project and my Markdown Monster project - notice how MM doesn't have a runtimes folder.

image

Aha! If I add an explicit reference to the Markdown Monster project, then the Runtimes folder shows up, and when it does the AnyCpu build works. Remove the project reference and rely on the transient reference from Westwind.WebView and the runtimes folder is not forwarded.

So the issue appears as follows:

When using a Transient NuGet Reference of Microsoft.Web.WebView2 the runtimes folder containing the WebView loader is not created which causes problems with non-x64 loads.

It looks like the x-64 runtime is the default and loaded from some other location as the x64 target works even without the runtimes folder present.

It seems to me the bug here is that the Transient WebView component reference is not forcing the runtimes folder to be created. It might need a few more inclusions on the NuGet package output?

yunate commented 1 year ago

Hi, @RickStrahl, thanks for your update. I am investigating this issue and I find a very similar issue on GitHub 6151 , could you help to try to see if this solution works for this issue as well?

champnic commented 1 year ago

Closing per @yunate's comment. If that still doesn't resolve the issue for you, please let me know and I can reopen. Thanks!