Closed ftppro closed 1 year ago
Could you post the whole call stack?
Here is the call stack when the error occurs:
[External Code]
MyApp.exe!MyApp.Form1.DoLogin() Line 116 C#
[Resuming Async Method]
[External Code]
MyApp.exe!MyApp.Program.Main() Line 19 C#
If I add any Button to the Form, the error does not occur. If I set the Visible property of that Button to false, the error occurs.
This is occurring because of MessageBox.Show("ok1");
. If you comment it out (or remove it), the issue doesn't occur.
The issue can be reproduced by creating a new form. (name: Form1). Then adding the following code to the form "Load" event handler. Then, from the menu, select "Debug", "Start Debugging".
*Note: The issue doesn't occur if you select "Debug", "Start Without Debugging"
private void Form1_Load(object sender, EventArgs e)
{
Microsoft.Web.WebView2.WinForms.WebView2 objWebView2 = new Microsoft.Web.WebView2.WinForms.WebView2();
objWebView2.Location = new System.Drawing.Point(10, 10);
objWebView2.Size = new System.Drawing.Size(800, 600);
objWebView2.Source = new Uri("https://www.google.com");
MessageBox.Show("ok1");
this.Controls.Add(objWebView2);
try
{
MessageBox.Show("ok2");
}
catch { }
}
As you also stated, the issue doesn't seem to occur if you add a button to the form, and run the program by selecting "Debug", "Start Debugging"--as long as the button is visible. If you change button's "Visible" property to false, the issue occurs again. This issue doesn't occur if you comment out (or remove) MessageBox.Show("ok1");
Here's the stack trace:
System.ArgumentException
HResult=0x80070057
Message=Value does not fall within the expected range.
Source=Microsoft.Web.WebView2.Core
StackTrace:
at Microsoft.Web.WebView2.Core.Raw.ICoreWebView2Controller.MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON reason)
at Microsoft.Web.WebView2.Core.CoreWebView2Controller.MoveFocus(CoreWebView2MoveFocusReason reason)
at Microsoft.Web.WebView2.WinForms.WebView2.OnEnter(EventArgs e)
at System.Windows.Forms.Control.NotifyEnter()
at System.Windows.Forms.ContainerControl.UpdateFocusedControl()
at System.Windows.Forms.ContainerControl.AssignActiveControlInternal(Control value)
at System.Windows.Forms.ContainerControl.ActivateControlInternal(Control control, Boolean originator)
at System.Windows.Forms.ContainerControl.SetActiveControlInternal(Control value)
at System.Windows.Forms.ContainerControl.set_ActiveControl(Control value)
at System.Windows.Forms.Control.Select(Boolean directed, Boolean forward)
at System.Windows.Forms.Form.set_Active(Boolean value)
at System.Windows.Forms.Form.WmActivate(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
The error still happens when MessageBox.Show("ok1"); is removed.
If you're trying to output some debugging messages. I think that you'll get better results if you use System.Diagnostics.Debug.WriteLine("your message");
instead of MessageBox.Show("your message");
. If you really want to use a MessageBox, you can do the following:
Thread t = new Thread(() => MessageBox.Show(text));
t.Start();
It's from a post on StackOverflow.
Try to "Clean" your project, then re-compile (Build => Clean
'Cleaning' did not fix the problem.
It appears that you are not waiting properly for WebView2 to initialize. Here is an example for you.
using System;
using System.Diagnostics;
using System.Windows.Forms;
using Microsoft.Web.WebView2.Core;
namespace WebView2
{
public partial class WebView : Form
{
public WebView()
{
this.Load += WebView2Test_Load;
InitializeComponent();
webView2.CoreWebView2Ready += webView_CoreWebView2Ready;
webView2.NavigationCompleted += browser_NavigationCompleted;
}
private void WebView2Test_Load(object sender, EventArgs e)
{
InitializeAsync();
}
async private void InitializeAsync()
{
await webView2.EnsureCoreWebView2Async(); // Wait for coreWebView2 initialization
}
private void browser_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
Debug.Print("Navigation Completed");
}
private void webView_CoreWebView2Ready(object sender, EventArgs e)
{
try
{
webView2.Source = new System.Uri("https://microsoft.com/", UriKind.Absolute);
}
catch (Exception ex)
{
Debug.Print(ex.ToString());
}
}
}
}
I took all the steps you suggested, and the problem still happens. Also, those steps don't explain why adding a button to the form causes the problem to not occur, and why that button must be visible.
Show your source code.
It looks like if one adds this.TopMost = true;
, the issue doesn't occur.
private void Form1_Load(object sender, EventArgs e)
{
this.TopMost = true;
Microsoft.Web.WebView2.WinForms.WebView2 objWebView2 = new Microsoft.Web.WebView2.WinForms.WebView2();
objWebView2.Location = new System.Drawing.Point(10, 10);
objWebView2.Size = new System.Drawing.Size(800, 600);
objWebView2.Source = new Uri("https://www.google.com");
MessageBox.Show("ok1");
this.Controls.Add(objWebView2);
try
{
MessageBox.Show("ok2");
}
catch { }
}
This is the stack trace before adding this.TopMost = true;
:
There's a post on StackOverflow, that may be useful.
You are not properly waiting for Webview2 to initialize fully. That is root cause.
I used exactly the code that was suggested, and the error still happened.
Adding "this.TopMost = true" just stopped the break from occurring when the error was thrown, and it made it impossible to close the app when debugging (by clicking the X in the upper right of the app's frame).
The only code you have shown does not wait properly for Webview2 to fully initialize.
Again, I used exactly the code that you suggested (including InitializeAsync, EnsureCoreWebView2Async(), and NavigationCompleted). The error still occurred. You still haven't explained why adding a do-nothing Button to the form eliminates the error.
I can't answer any questions about causation until I see exactly what you are doing.
It's probably better to know what you are trying to accomplish, rather than trying to figure out why your usage of MessageBox, for debugging purposes, isn't working. Or as @mikemeinz said, show your code. You can zip it up and attach it, if you don't want to paste it. If your project has a lot of code, create another project that only demonstrates your usage of the WebView2 control.
I will try to explain the cause of the problem a bit differently. Because you are not properly waiting for initialization to finish before setting the Source property, Webview2 will eventually throw an exception. That exception will interrupt your program at whatever step it happens to be executing. Whether it is a Message Box, a For loop, a computation, etc. makes no difference. It fails because Webview2 throws the exception. The Call Stack display shows that it is Webview2 throwing the exception.
Give the following code a try. It incorporates the code @mikemeinz posted, as well as some code from Getting started with WebView2 in Windows Forms apps (Preview). Add a form named "Form1" to your project, and then add the code below, changing the namespace name to your projects namespace.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using Microsoft.Web.WebView2;
using System.Diagnostics;
namespace TestWebView2
{
public partial class Form1 : Form
{
//create new instance of WebView2
Microsoft.Web.WebView2.WinForms.WebView2 objWebView2 = new Microsoft.Web.WebView2.WinForms.WebView2();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
InitializeAsync();
//set WebView2 properties and add to form
objWebView2.Location = new System.Drawing.Point(10, 10);
objWebView2.Size = new System.Drawing.Size(800, 600);
objWebView2.Source = new Uri("about:blank");
this.Controls.Add(objWebView2);
try
{
MessageBox.Show("ok1");
if (objWebView2 != null && objWebView2.CoreWebView2 != null)
{
//navigate to website
objWebView2.CoreWebView2.Navigate("https://www.google.com"); //option 1
//objWebView2.Source = new Uri("https://www.google.com", UriKind.Absolute); //option 2
}//if
MessageBox.Show("ok2");
}
catch (Exception ex)
{
Debug.Print("Error (Form1_Load): " + ex.Message);
}
}
private void ObjWebView2_CoreWebView2Ready(object sender, EventArgs e)
{
Debug.Print("Info: ObjWebView2_CoreWebView2Ready");
}
private async void InitializeAsync()
{
// wait for coreWebView2 initialization
await objWebView2.EnsureCoreWebView2Async();
//add event handlers
objWebView2.CoreWebView2Ready += ObjWebView2_CoreWebView2Ready;
objWebView2.NavigationStarting += ObjWebView2_NavigationStarting;
objWebView2.CoreWebView2.NavigationCompleted += CoreWebView2_NavigationCompleted;
objWebView2.NavigationCompleted += ObjWebView2_NavigationCompleted;
}
private void ObjWebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
Debug.Print("Info: ObjWebView2_NavigationCompleted");
}
private void CoreWebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
Debug.Print("Info: CoreWebView2_NavigationCompleted");
}
private void ObjWebView2_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
{
Debug.Print("Info: Navigating to '" + objWebView2.Source + "'");
}
}
}
There isn't a lot of documentation yet, so any feedback on improvements to my code is welcomed.
@cgeier I rearranged your code. It is important to not use WebView2 control until CoreWebView2Ready event is thrown.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using Microsoft.Web.WebView2;
using System.Diagnostics;
namespace TestWebView2
{
public partial class Form1 : Form
{
//create new instance of WebView2
Microsoft.Web.WebView2.WinForms.WebView2 objWebView2 = new Microsoft.Web.WebView2.WinForms.WebView2();
public Form1()
{
InitializeComponent();
//add event handler
objWebView2.CoreWebView2Ready += ObjWebView2_CoreWebView2Ready;
//set WebView2 properties and add to form
objWebView2.Location = new System.Drawing.Point(10, 10);
objWebView2.Size = new System.Drawing.Size(800, 600);
objWebView2.Source = new Uri("about:blank");
this.Controls.Add(objWebView2);
}
private void Form1_Load(object sender, EventArgs e)
{
InitializeAsync();
}
private void ObjWebView2_CoreWebView2Ready(object sender, EventArgs e)
{
Debug.Print("Info: ObjWebView2_CoreWebView2Ready");
try
{
MessageBox.Show("ok1");
if (objWebView2 != null && objWebView2.CoreWebView2 != null)
{
//navigate to website
objWebView2.CoreWebView2.Navigate("https://www.google.com"); //option 1
//objWebView2.Source = new Uri("https://www.google.com", UriKind.Absolute); //option 2
}//if
MessageBox.Show("ok2");
}
catch (Exception ex)
{
Debug.Print("Error (Form1_Load): " + ex.Message);
}
}
private async void InitializeAsync()
{
// wait for coreWebView2 initialization
await objWebView2.EnsureCoreWebView2Async();
//add event handlers
objWebView2.NavigationStarting += ObjWebView2_NavigationStarting;
objWebView2.CoreWebView2.NavigationCompleted += CoreWebView2_NavigationCompleted;
objWebView2.NavigationCompleted += ObjWebView2_NavigationCompleted;
}
private void ObjWebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
Debug.Print("Info: ObjWebView2_NavigationCompleted");
}
private void CoreWebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
Debug.Print("Info: CoreWebView2_NavigationCompleted");
}
private void ObjWebView2_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
{
Debug.Print("Info: Navigating to '" + objWebView2.Source + "'");
}
}
}
@mikemeinz thanks for the help improving the code. I've converted the code, that you re-arranged, to VB .NET. Perhaps it will be useful to someone.
Imports Microsoft.Web.WebView2.Core
Imports Microsoft.Web.WebView2.WinForms
Imports System.Diagnostics
Public Class Form1
'create new instance of WebView2
Dim objWebView2 As Microsoft.Web.WebView2.WinForms.WebView2 = New Microsoft.Web.WebView2.WinForms.WebView2()
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
'add event handler
AddHandler objWebView2.CoreWebView2Ready, AddressOf ObjWebView2_CoreWebView2Ready
'set WebView2 properties and add to form
objWebView2.Location = New System.Drawing.Point(10, 10)
objWebView2.Size = New System.Drawing.Size(800, 600)
objWebView2.Source = New Uri("about:blank")
Me.Controls.Add(objWebView2)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
InitializeAsync()
End Sub
Private Async Sub InitializeAsync()
'wait for coreWebView2 initialization
Await objWebView2.EnsureCoreWebView2Async()
'add event handlers
AddHandler objWebView2.NavigationStarting, AddressOf ObjWebView2_NavigationStarting
AddHandler objWebView2.CoreWebView2.NavigationCompleted, AddressOf CoreWebView2_NavigationCompleted
AddHandler objWebView2.NavigationCompleted, AddressOf ObjWebView2_NavigationCompleted
End Sub
Private Sub ObjWebView2_CoreWebView2Ready(ByVal sender As Object, ByVal e As System.EventArgs)
Debug.Print("Info: ObjWebView2_CoreWebView2Ready")
Try
MessageBox.Show("ok1")
If (objWebView2 IsNot Nothing AndAlso objWebView2 IsNot Nothing) Then
objWebView2.CoreWebView2.Navigate("https://www.google.com") 'option 1
'objWebView2.Source = New Uri("https://www.google.com", UriKind.Absolute) 'option 2
End If
MessageBox.Show("ok2")
Catch ex As Exception
Debug.Print("Error (ObjWebView2_CoreWebView2Ready): " + ex.Message)
End Try
End Sub
Private Sub ObjWebView2_NavigationCompleted(ByVal sender As Object, ByVal e As Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs)
Debug.Print("Info: ObjWebView2_NavigationCompleted")
End Sub
Private Sub CoreWebView2_NavigationCompleted(ByVal sender As Object, ByVal e As Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs)
Debug.Print("Info: CoreWebView2_NavigationCompleted")
End Sub
Private Sub ObjWebView2_NavigationStarting(ByVal sender As Object, ByVal e As Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs)
Debug.Print("Info: ObjWebView2_NavigationStarting")
End Sub
End Class
It's been a while since I've written any VB .NET code, so any suggestions for improvement are welcomed.
@ftppro @mikemeinz
It appears that some of the code that I posted above is flawed.
Instead of:
private void Form1_Load(object sender, EventArgs e)
{
....
}
it should be:
private async void Form1_Load(object sender, EventArgs e)
{
....
}
Instead of:
private async void InitializeAsync()
{
....
}
it should be:
private async Task InitializeAsync()
{
....
}
This allows one to do the following:
private async void Form1_Load(object sender, EventArgs e)
{
//initialize CoreWebView2
await InitializeAsync();
}
without this "await" in the "Load" event handler, the code won't execute in the expected order.
Here's a corrected example:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using System.Diagnostics;
namespace TestWebView2
{
public partial class Form1 : Form
{
//create new instance of WebView2
Microsoft.Web.WebView2.WinForms.WebView2 webView21 = new Microsoft.Web.WebView2.WinForms.WebView2();
public Form1()
{
InitializeComponent();
//set WebView2 properties and add to form
webView21.Location = new System.Drawing.Point(10, 10);
webView21.Size = new System.Drawing.Size(800, 600);
//don't set source property here
this.Controls.Add(webView21);
}
private async void Form1_Load(object sender, EventArgs e)
{
// add event handler
webView21.CoreWebView2Ready += webView21_CoreWebView2Ready;
Debug.Print("Info: initializing CoreWebView2");
//initialize CoreWebView2
await InitializeAsync();
Debug.Print("Info: after initializing CoreWebView2");
if (webView21 != null && webView21.CoreWebView2 != null)
{
//navigate to website - option 1
webView21.Source = new Uri("https://www.microsoft.com", UriKind.Absolute);
//navigate to website - option 2
//webView21.CoreWebView2.Navigate("https://www.microsoft.com");
}//if
}
private void webView21_CoreWebView2Ready(object sender, EventArgs e)
{
Debug.Print("Info: webView21_CoreWebView2Ready");
//subscribe to events (add event handlers) - CoreWebView2
webView21.CoreWebView2.NavigationCompleted += CoreWebView2_NavigationCompleted;
//subscribe to events (add event handlers) - WebView2
webView21.NavigationStarting += webView21_NavigationStarting;
webView21.NavigationCompleted += webView21_NavigationCompleted;
Debug.Print("Info: leaving webView21_CoreWebView2Ready");
}
private async Task InitializeAsync()
{
Debug.Print("Info: before EnsureCoreWebView2Async");
// wait for coreWebView2 initialization
await webView21.EnsureCoreWebView2Async();
Debug.Print("Info: after EnsureCoreWebView2Async");
}
private void webView21_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
Debug.Print("Info: webView21_NavigationCompleted");
}
private void CoreWebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
Debug.Print("Info: CoreWebView2_NavigationCompleted");
}
private void webView21_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
{
Debug.Print("Info: webView21_NavigationStarting - Navigating to '" + e.Uri.ToString() + "'");
}
}
}
The VB .NET code I posted has the same flaw as mentioned for the C# code. One needs to call "InitializeAsync" with "Await" in the "Load" event handler, otherwise the code doesn't execute in the expected order. Below is the corrected code with some modifications.
Imports Microsoft.Web.WebView2.Core
Imports Microsoft.Web.WebView2.WinForms
Imports System.Threading.Tasks
Imports System.Diagnostics
Public Class Form1
Private WithEvents WebView21 As Microsoft.Web.WebView2.WinForms.WebView2 = New Microsoft.Web.WebView2.WinForms.WebView2
Private WithEvents CoreWebView21 As Microsoft.Web.WebView2.Core.CoreWebView2
Public Sub New()
' This call is required by the designer.
InitializeComponent()
'set WebView2 properties And add to form
WebView21.Location = New System.Drawing.Point(10, 10)
WebView21.Size = New System.Drawing.Size(800, 600)
'don't set source property here
Me.Controls.Add(WebView21)
End Sub
Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Debug.Print("Info: initializing CoreWebView2")
'initialize CoreWebView2
Await InitializeAsync()
Debug.Print("Info: after initializing CoreWebView2")
'set value
CoreWebView21 = WebView21.CoreWebView2
If (WebView21 IsNot Nothing AndAlso WebView21.CoreWebView2 IsNot Nothing) Then
'navigate to website - option 1
WebView21.Source = New Uri("https://www.microsoft.com", UriKind.Absolute)
'navigate to website - option 2
'WebView21.CoreWebView2.Navigate("https://www.microsoft.com")
End If
End Sub
Private Async Function InitializeAsync() As Task
Debug.Print("Info: before EnsureCoreWebView2Async")
'wait for coreWebView2 initialization
Await WebView21.EnsureCoreWebView2Async()
Debug.Print("Info: after EnsureCoreWebView2Async")
End Function
Private Sub CoreWebView21_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs) Handles CoreWebView21.NavigationCompleted
Debug.Print("Info: CoreWebView21_NavigationCompleted")
End Sub
Private Sub WebView21_CoreWebView2Ready(ByVal sender As Object, ByVal e As System.EventArgs) Handles WebView21.CoreWebView2Ready
Debug.Print("Info: WebView21_CoreWebView2Ready")
Debug.Print("Info: leaving WebView21_CoreWebView2Ready")
End Sub
Private Sub WebView21_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs) Handles WebView21.NavigationCompleted
Debug.Print("Info: WebView21_NavigationCompleted")
End Sub
Private Sub WebView21_NavigationStarting(sender As Object, e As CoreWebView2NavigationStartingEventArgs) Handles WebView21.NavigationStarting
Debug.Print("Info: WebView21_NavigationStarting - Navigating to '" & e.Uri.ToString() & "'")
End Sub
End Class
Closing old issue. Please let me know if we need to re-open this for any reason.
The code below exemplifies that MessageBox.Show() fails after WebView2 is added to a form.
MessageBox.Show("ok2") throws the following error, even though it is in a try block: System.ArgumentException: 'Value does not fall within the expected range.';
My versions: Windows 10 Home Version 2004, installed 5/29/20 Microsoft.Web.WebView2 v.0.9.538-prerelease Visual Studio 2017 version 15.0 .NET Framework 4.8.04084 Microsoft Edge Version 86.0.569 (Canary 64-bit)