MicrosoftEdge / WebView2Feedback

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

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

Open gallderhen opened 1 year ago

gallderhen commented 1 year ago

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.

victorthoang commented 1 year ago

Hello @gallderhen,

Thanks for your question. One of our devs will take a look at your question and get back to you.

Typically, we prioritize bugs and feature requests first so please be patient as we work through our backlog and priorities!

hein commented 1 year ago

Hi @victorthoang and @oggy22

Just want to keep this question alive, in the hope that there may be an answer for me 🙂

-G-

CarsonSlovoka commented 1 year ago

Even though I have done CoInitializeEx I also encounter this error when I try to minimize(SW_MINIMIZE) the window while it is being created. It works fine if I use SW_SHOW, or if I don't set it at all.

WndProc: func(hwnd HWND, uMsg UINT, wParam WPARAM, lParam LPARAM) LRESULT {
                switch uMsg {
                case w32.WM_CREATE:
                    // ShowWindow(hwnd, SW_SHOW) // OK
                    ShowWindow(hwnd, SW_MINIMIZE) // Error: Creating environment failed with CoInitialize has not been called.
                }
                return DefWindowProc(hwnd, uMsg, wParam, lParam)
            })
novac42 commented 1 year ago

Hi @gallderhen , does the problem still exist with latest runtime and SDK? If yes could you please collect ETW trace for troubleshooting and share with us? Guidance: WebView2Feedback/diagnostics/etw.md at main · MicrosoftEdge/WebView2Feedback (github.com)

RSN1907 commented 3 months ago

@novac42 We see below exception when creating webview2 environment One or more errors occurred. (CoInitialize has not been called. (0x800401F0 (CO_E_NOTINITIALIZED))) InnerException CoInitialize has not been called. (0x800401F0 (CO_E_NOTINITIALIZED))

at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode) at Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(String browserExecutableFolder, String userDataFolder, CoreWebView2EnvironmentOptions options)

We have collected etl traces, can you kindly suggest how to upload the trace ,trace is 62 MB and maximum allowed file is 25 MB

RSN1907 commented 3 months ago

@novac42 @victorhuangwq Should I create new ticket for above issue?

victorhuangwq commented 3 months ago

Hi @RSN1907 yes, could you please create a new ticket?