MicrosoftEdge/WebView2Feedback

WebView2 application doesn't work when installed in Program Files folder

Closed this issue ยท 20 comments

I tried the example given by microsoft, C# Winforms .NET application https://docs.microsoft.com/en-us/microsoft-edge/webview2/gettingstarted/winforms
it works perfectly in debug mode, but when install the program in the Program Files folder, the Navigate function does not work, I get
"Error HRESULT E_FAIL has been returned from a call to a COM component.
System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has been returned from a call to a COM component. "
In fact CoreWebView2 is not initialized.

If install the application in a folder other than C:\Program files (86) it works, for example it works fine in a C:\TEST

Is there a trick to make it work in any folder including C: Program files (86)?

Webview2 0.9.538 prerelease
Canary Version 85.0.554.0
VS2019 Framework 4.62
C# or VB Winforms
target CPU platform x86

AB#30555792

It could be that it fails because WebView2 can't create the data/cache folder in the program files directory due to permissions. You can try changing the WebView2 data/cache directory on creation.
Read 271 and 295 for some suggestions.

@michael-russin is correct.

If the program is to be installed in the Program Files folder, you need to use CoreWebView2Environment and specify the user data folder?

Checkout our user data folder document here: https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/userdatafolder

It would be good to improve the error message, and provide the link to the docs (e.g. aka.ms/bla).

Yes, we should try to improve the error message in this case. The problem is, probably, as others noted, access denied to a path.

What is the correct procedure for this. The Microsoft documentation doesn't show any working examples.
Here is what I tried (I have a EdgeBrowser WinForms component):

    var userDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\OurSoftware";
    var env = await CoreWebView2Environment.CreateAsync(null, userDataFolder);
    await this.EdgeBrowser.EnsureCoreWebView2Async(env);

I validated that userDataFolder is C:\Users\myuser\AppData\Local\OurSoftware
It still creates the user data folder in the same location as the EXE though.

So how does one use the environment, as what would seem obvious does not work?

What is the correct procedure for this. The Microsoft documentation doesn't show any working examples.
Here is what I tried (I have a EdgeBrowser WinForms component):

    var userDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\OurSoftware";
    var env = await CoreWebView2Environment.CreateAsync(null, userDataFolder);
    await this.EdgeBrowser.EnsureCoreWebView2Async(env);

I validated that userDataFolder is C:\Users\myuser\AppData\Local\OurSoftware
It still creates the user data folder in the same location as the EXE though.

So how does one use the environment, as what would seem obvious does not work?

Thanks for this, I got it working but I figured out a few things. "EnsureCoreWebView2Async" has to run before the "Source" value is set. So what I did is go to designer file and comment the source value (this.webView21.Source = new System.Uri("about:blank", System.UriKind.Absolute);) and then in my browser form constructor I have something like this:

public BrowserForm(string url = null)
        {
            InitializeComponent();
            InitializeBrowser(url);

        }
private async void InitializeBrowser(string url = null)
        {
            var userDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\SoftwareName";
            var env = await CoreWebView2Environment.CreateAsync(null, userDataFolder);
            await webView21.EnsureCoreWebView2Async(env);
            webView21.Source = new UriBuilder(url ?? Settings.Default.HomePage).Uri;
        }

I hope that helps :)

Stay away from async void, use async Task instead.

Stay away from async void, use async Task instead.

Thank you for the tip! ๐Ÿ˜

I found that if you pump the message loop that you can utilize await, like this (sorry, it's in VB.net, use a conversion extension it if you need C#)

    Private Function AwaitSync(Of T)(task As Task(Of T)) As T
        Do While Not task.IsCompleted
            Windows.Forms.Application.DoEvents()
            Threading.Thread.Sleep(1)
        Loop

        Return task.Result
    End Function
    Private Async Function Init() As Task(Of Boolean)
        Dim userDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & "\Somefolder"
        Dim env = Await CoreWebView2Environment.CreateAsync(Nothing, userDataFolder)
        Await Me.EdgeBrowser.EnsureCoreWebView2Async(env)
 ...
    End Function

Then you can call AwaitSync(Init())

Also, make sure you don't set the .Source property until AFTER you have called EnsureCoreWebView2Async( ), or it will throw errors on some systems.

Hi, just a small comment from a Dinosaur of programming: Thanks for creating the WebView2 component letting us Dinosaurs of the desktop be able to use a browser in our applications that is better than IE.
Thanks to Djst3Rios for sharing the call to initialize the UserDataFolder.
And a Complaint: Can you ask the people who mantains the https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/userdatafolder indicated by pagoe-msft and ask them to add the sample code so that we don't have to search around for hours to find this post. Because unfortunately those who create Desktop Applications Install them on Program Files which does not allow the UserData to be created by the component.
Also including this in the Getting Started for Winforms and WPF would be really nice.
Sabrina

Hi @SabrinaCs - sorry for the delay in response. We are actively working on improving the experience around using the User Data Folder. I'll make sure the documentation updates are captured there as well. Thanks!

What is the correct procedure for this. The Microsoft documentation doesn't show any working examples.
Here is what I tried (I have a EdgeBrowser WinForms component):

    var userDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\OurSoftware";
    var env = await CoreWebView2Environment.CreateAsync(null, userDataFolder);
    await this.EdgeBrowser.EnsureCoreWebView2Async(env);

I validated that userDataFolder is C:\Users\myuser\AppData\Local\OurSoftware
It still creates the user data folder in the same location as the EXE though.
So how does one use the environment, as what would seem obvious does not work?

Thanks for this, I got it working but I figured out a few things. "EnsureCoreWebView2Async" has to run before the "Source" value is set. So what I did is go to designer file and comment the source value (this.webView21.Source = new System.Uri("about:blank", System.UriKind.Absolute);) and then in my browser form constructor I have something like this:

public BrowserForm(string url = null)
        {
            InitializeComponent();
            InitializeBrowser(url);

        }
private async void InitializeBrowser(string url = null)
        {
            var userDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\SoftwareName";
            var env = await CoreWebView2Environment.CreateAsync(null, userDataFolder);
            await webView21.EnsureCoreWebView2Async(env);
            webView21.Source = new UriBuilder(url ?? Settings.Default.HomePage).Uri;
        }

I hope that helps :)

@DjSt3rios You are a legend man!
Commenting out the Source property in the Designer solved it for me. I spent more than a day trying to fix this issue.
May I ask how did you figure out the Source property there is the one causing the issue which still uses the cache in the same folder as the application?

What is the correct procedure for this. The Microsoft documentation doesn't show any working examples.
Here is what I tried (I have a EdgeBrowser WinForms component):

    var userDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\OurSoftware";
    var env = await CoreWebView2Environment.CreateAsync(null, userDataFolder);
    await this.EdgeBrowser.EnsureCoreWebView2Async(env);

I validated that userDataFolder is C:\Users\myuser\AppData\Local\OurSoftware
It still creates the user data folder in the same location as the EXE though.
So how does one use the environment, as what would seem obvious does not work?

Thanks for this, I got it working but I figured out a few things. "EnsureCoreWebView2Async" has to run before the "Source" value is set. So what I did is go to designer file and comment the source value (this.webView21.Source = new System.Uri("about:blank", System.UriKind.Absolute);) and then in my browser form constructor I have something like this:

public BrowserForm(string url = null)
        {
            InitializeComponent();
            InitializeBrowser(url);

        }
private async void InitializeBrowser(string url = null)
        {
            var userDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\SoftwareName";
            var env = await CoreWebView2Environment.CreateAsync(null, userDataFolder);
            await webView21.EnsureCoreWebView2Async(env);
            webView21.Source = new UriBuilder(url ?? Settings.Default.HomePage).Uri;
        }

I hope that helps :)

@DjSt3rios You are a legend man!
Commenting out the Source property in the Designer solved it for me. I spent more than a day trying to fix this issue.
May I ask how did you figure out the Source property there is the one causing the issue which still uses the cache in the same folder as the application?

Glad I could help. I use Visual Studio, so when I hovered over the function "EnsureCoreWebView2Async", in the description it says it will have no effect after setting the "Source" property.
image

I've written an article with a sample that configures the user data you can find it here
https://www.sabrinacosolo.com/net-5-webview2-un-browser-moderno-nelle-app-desktop/
it is in italian sorry but you can download the working project.

@DjSt3rios
Can't believe I missed that.
Now, I have a problem, when I test my application in Program Files (x86) Directory, My application runs fine.

But when I run against the Octopus Deploy application, which is in the network "ssgprd/Octopus/MyAppName"
I am getting the following error:
image
image
Do you have any idea what the issue is?

The folder LocalData is created when I test my app in Program Files (x86) Directory
image

But when I test in the Octopus Deployed Application, the folder "WebView" is created but empty:
image

@limyandi The error says that a collection was modified while it was being enumerated. So perhaps you have a for/foreach loop and inside of it you modify the collection you are currently going through?

code it working perfect for me

public ControlDocument()
        {
            InitializeComponent();
            InitializeBrowser();
        }
        private async Task InitializeBrowser()
        {
            var userDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\AppName";
            var env = await CoreWebView2Environment.CreateAsync(null, userDataFolder);
            await webView.EnsureCoreWebView2Async(env);
            webView.Source = new Uri("https://here.com") ;
        }

Thanks! Literally stuck on this issue for 2 days, was certain it was a dependency issue. I've recreated my setup project more than 10 times!

Glad it's finally working now.

Hey all - We've decided we aren't going to make further product or API changes here. We've improved the error messaging around this to make it both clearer when the user data folder can't be created, and added an error message when a dev is trying to set Source property which is overriding the explicit initialization with a user data folder. We've also updated our docs. Any further change would be a large breaking change, as well as introducing potentially bad practices around user data folder cleanup when uninstalling. Thanks!
https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/user-data-folder

We weren't able to get any of the above mentioned solutions to work in our Blazor Maui app, but we found another workaround.

During installation of the application, we create the folder {AppName}.exe.WebView2 in the installation directory, and give all users read/write access with the command icacls {path} /t /grant *S-1-1-0:f. (The folder {AppName}.exe.WebView2 is created if running the application from a folder not under Program files, and the application does not work in Program files as this folder with its content cannot be created without admin rights).

Relevant links: