MicrosoftEdge / MicrosoftEdge/WebView2Feedback

CoInitialize error when trying to initialize a webview2 component from a DLL

Open
#2,857 7 comments 0 reactions 1 assignee View on GitHub

Nobody has claimed this yet.

bug
Dominant language
PowerShell
Stars
526
Forks
67
PR merge metrics
No merged PRs in 30d

Description

Hi,

I posted the following on stackoverflow but had no luck of a reply, so I thought I'd try here.

The following code is kind of a mish-mash I've slap together from examples and tutorials I found on the internet.

The premise of the code is to create a webview2 component in a winform, where the winform is a DLL that gets loaded by a third-party application.

Now, the third-party application loads my DLL and calls this function:

Integrations::ShowForm("Form1");

My winform is a basic C# Windows Forms App using .Net Framework.

My Form1.cs looks as follows:

namespace GuiIntegrations
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            string webview2DllPath = @"C:\TestFolder\runtimes\win-x64\native";
            CoreWebView2Environment.SetLoaderDllFolderPath(webview2DllPath);
            Environment.SetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER", @"C:\TestFolder\user-data");
            InitializeComponent();
            _ = InitializeAsync();
        }
    }
}

My Form1.Designer.cs file looks like:

namespace GuiIntegrations
{
    public partial class Form1 : Form
    {
        private System.ComponentModel.IContainer components = null;
        #region Windows Form Designer generated code
        ...
        #endregion

        private Microsoft.Web.WebView2.WinForms.WebView2 webView21;
        
        async Task InitializeAsync()
        {
            try
            {
                string webview2FixedPath = @"C:\TestFolder\Microsoft.WebView2.FixedVersionRuntime.105.0.1343.33.x64";

                var env = await CoreWebView2Environment.CreateAsync(browserExecutableFolder: webview2FixedPath , userDataFolder: @"C:\TestFolder\user-data");

                await webView21.EnsureCoreWebView2Async(env);

                webView21.Source = new Uri("https://www.google.com");
            }
            catch (Exception e)
            {
                // The exception goes into an event-list that can be processed outside the DLL
            }
        }
    }
}

(The excluded #region is just your normal winform generated code). Also in the DLL is a class called Integrations.cs, that looks like this:

namespace GuiIntegrations
{
    public static class Integrations
    {
        private static Form1 form;
        private static Thread formThread;

        [STAThread]
        public static void ShowForm(string formName)
        {
            try
            {
                Assembly assembly = Assembly.GetExecutingAssembly();
                Type[] types = assembly.GetTypes();
                foreach (Type type in types)
                {
                    if (type.BaseType == typeof(Form) && type.Name == formName)
                    {
                        object obj_form = type.Assembly.CreateInstance(type.FullName);
                        form = (Form1)obj_form;
                        formThread = new Thread(() => Application.Run(form));
                        formThread.SetApartmentState(ApartmentState.STA);
                        formThread.Start();
                        Thread.Sleep(200);
                    }
                }
            } catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }
    }
}

Apologies that its not the most eloquent source (and this editor of github doesnt like my code-sections), but I kind of did it on the fly.

FYI:

C:\TestFolder\runtimes\win-x64\native is the location for the 'WebView2Loader.dll' DLL of the webview2 component.
my winform DLL location also contains the 3 other webview2 DLLs Microsoft.Web.WebView2.Core.dll, Microsoft.Web.WebView2.WinForms.dll, Microsoft.Web.WebView2.Wpf.dll
C:\TestFolder\Microsoft.WebView2.FixedVersionRuntime.105.0.1343.33.x64 is the extracted location of the fixed runtime for webview2.
The problem occurs when 'CoreWebView2Environment.CreateAsync' is called. As soon as its executed, it throws an exception 'Exception: CoInitialize has not been called. (Exception from HRESULT: 0x800401F0 (CO_E_NOTINITIALIZED)'.

As far as I could determine from the error, its not entering the single-apartment state, which is strange considering that I am setting the thread-state that starts the form as STA.

I've also checked that my component doesn't contain a 'Source' field: ComponentProperties

Any help would be greatly appreciate.

PS. When I compile the program as a Windows Application and run it, the component loads fine and shows the google page.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.