6

I'm trying to create an app that uses the WebView2 WPF component. Currently I'm working on logging the messages and errors that are written by the javascript code of the websites using console.log().

This is what I have right now:

public partial class WebView2BrowserControl : WebView2
{
    private async void OnWebViewLoaded(object sender, RoutedEventArgs e)
    {
        await EnsureCoreWebView2Async();
        if (showDeveloperTools)
        {
            CoreWebView2.GetDevToolsProtocolEventReceiver("Log.entryAdded").DevToolsProtocolEventReceived += OnConsoleMessage;
            CoreWebView2.OpenDevToolsWindow();
        }
        else
        {
            CoreWebView2.Settings.AreDevToolsEnabled = false;
        }
    }

    private void OnConsoleMessage(object sender, CoreWebView2DevToolsProtocolEventReceivedEventArgs e)
    {
        if (e != null && e.ParameterObjectAsJson != null)
        {
            Trace.WriteLine("WebView2:" + e.ParameterObjectAsJson);
        }
    }
}

As you can see, I'm using the GetDevToolsProtocolEventReceiver method to subscribe to events in the DevTools. The documentation states the following:

eventName:String - The full name of the event in the format {domain}.{event}. For more information about DevToolsProtocol events description and event args, navigate to DevTools Protocol Viewer.

...And acording to the DevTools Protocol Viewer the event that I'm looking for is Log.entryAdded.

Now the problem is that while the GetDevToolsProtocolEventReceiver("Log.entryAdded") call does not throw any exception the event is never raised, even if I can see things being logged in DevTools. I even tried writing my own console.log() calls in the DevTools window.

Other things that I've tried:

  • using both the Evergreen Standalone Installer which installs WebView2 on the machine or the Fixed Version (both 87 and 88 versions) which is basically a portable version of WebView2
  • using both latest stable version of Microsoft.Web.View2.Core.dll from NuGet which is 1.0.705.50 and latest pre-release version
  • using both Log.entryAdded event and Console.messageAdded (deprecated)
  • subscribing to the event after I open the DevTools window

So what am I doing wrong?

Norberth Csorba
  • 312
  • 1
  • 9
  • yes, it's set to true because the DevTools window opens up, and I've also checked with the debugger that the code in if-statement runs – Norberth Csorba Feb 21 '21 at 17:08

2 Answers2

6

You're close!

It turns out, you have to enable the protocol event, or it will not be called.

Just enable it after you you have added the event listener, like this:

CoreWebView2.GetDevToolsProtocolEventReceiver("Log.entryAdded").DevToolsProtocolEventReceived += ConsoleMessage;
await CoreWebView2.CallDevToolsProtocolMethodAsync("Log.enable", "{}");

Now you should get messages in your trace.

Alternative for Windows Forms (after you have installed and dropped a WebView2 on your form:

private async void Form1_Load(object sender, EventArgs e)
{
    await webView21.EnsureCoreWebView2Async();
}

private async void WebView21_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
    webView21.CoreWebView2.GetDevToolsProtocolEventReceiver("Log.entryAdded").DevToolsProtocolEventReceived += ConsoleMessage;
    await webView21.CoreWebView2.CallDevToolsProtocolMethodAsync("Log.enable", "{}");
    webView21.CoreWebView2.OpenDevToolsWindow();
    webView21.CoreWebView2.Navigate("https://stackoverflow.com");

}

private void ConsoleMessage(object sender, Microsoft.Web.WebView2.Core.CoreWebView2DevToolsProtocolEventReceivedEventArgs e)
{
    if (e != null && e.ParameterObjectAsJson != null)
    {
        Console.WriteLine("WebView2:" + e.ParameterObjectAsJson);
    }
}
Poul Bak
  • 10,450
  • 5
  • 32
  • 57
  • That's it! Thanks! It seems that another thing that prevents me from receiving events is the fact that I'm using some iframes inside the page. For stackoverflow.com your solution works, but for some page with iframes inside it doesn't. Do you know how to tell WebView2 "Hey, I want to load page x but listen to DevTools events from iframes inside"? – Norberth Csorba Feb 22 '21 at 08:41
  • 3
    using the deprecated [Console Domain](https://chromedevtools.github.io/devtools-protocol/tot/Console/) seems to solve the problem described in previous comment – Norberth Csorba Feb 22 '21 at 10:14
  • Glad, you found a working solution. Happy coding. – Poul Bak Feb 22 '21 at 17:26
1

The accepted answer didn't work for me.

It is using the Log domain, to make it work, which is for chromium logging messages.

I had to use Runtime domain, which allowed me to access the console.log.

Main code:

        async void InitializeAsync()
        {
            await webView.EnsureCoreWebView2Async(null);
            DevToolsProtocolHelper helper = webView.CoreWebView2.GetDevToolsProtocolHelper();
            await helper.Runtime.EnableAsync();
            helper.Runtime.ConsoleAPICalled += Runtime_ConsoleAPICalled;
        }

        private void Runtime_ConsoleAPICalled(object sender, Runtime.ConsoleAPICalledEventArgs e)
        {
            String test = e.Args[0].Value.ToString();
            Trace.WriteLine(test);
        }
justadev
  • 1,168
  • 1
  • 17
  • 32
  • Nothing changed in the DevTools protocol, the OP was using the log domain, which needed to be enabled, you are using the runtime domain, so you need to explicitly enable it. Each domain has it's own method to enable. https://chromedevtools.github.io/devtools-protocol/tot/Runtime/ – amaitland Jun 30 '22 at 20:35
  • I tried with the code in the accepted answer, it didn't work. The accepted answer has the `Log.enable`, so I don't know why it doesn't work. If someone has the same issue, maybe good to know that possible to try the Runtime as well – justadev Jul 01 '22 at 08:16
  • The question was originally about the log domain, so the answer is specific to that. My point is that you want events for the runtime domain to fire you call Runtime.enable, just as if you would call Network.enable for events from the network domain to fire and so on. You are speculating something changed with the DevTools protocol, which I'm telling you is incorrect, nothing changed. – amaitland Jul 01 '22 at 09:24
  • The OP wanted to get access to the `console.log` (as I did). He read in the docs that he should get it from Log domain. Like I said, I tried it, and for me it didn't work using the Log domain. I agree that my comment about a change in the API is not in place, since I have no info about that. I can remove the comment, if you think it is better. The main reason I added the answer is because Runtime worked, and Log didn't, and I thought it might help others in the future. – justadev Jul 01 '22 at 12:23
  • Both answers need some clarity, the log domain isn't for console logging, it's for chromium logging messages. So for accessing the console log the method you've used is correct, simplify your answer. – amaitland Jul 01 '22 at 19:29