首页 > 解决方案 > 等待 DevTools 加载

问题描述

如何检测 DevTools 何时完成加载?

ShowDevTools()在 CefSharp 中,您可以使用扩展方法调出 DevTools 窗口。我想指示嵌入式浏览器仅在加载 DevTools 之后加载页面(特别是在它附加其 JavaScript 调试器之后)。但是,ShowDevTools()似乎是异步执行的。

标签: c#google-chrome-devtoolscefsharpchromium-embedded

解决方案


在一些错误的开始之后,ShowDevToolsAsync下面显示的我的扩展方法似乎可以可靠地工作。

注意我正在使用https://stackoverflow.com/a/7809413/3063273的修改来检测 DevTools 何时完成加载。我不确定更可靠的选择是什么。也许您可以ILoadHandler.OnFrameLoadEnd像对 OP 建议的评论一样喜欢并从那里开始工作。我尝试了这条路,但在我能够让这个解决方案工作之前没有走得足够远,我认为这更直接和明显。

重要提示:您的实例ChromiumWebBrowser需要已经加载了一个网页(或至少开始加载一个网页),否则DevTools将永远不会钩入它,但只会坐在那里并显示以下消息:

DevTools 与页面断开连接

如果您想在加载页面之前确保 DevTools 已启动(例如,为了保证其 Javascript 调试器已准备好捕捉最早的错误),则让您ChromiumWebBrowser加载一个虚拟页面,例如<html>Loading DevTools...</html>,然后等待 DevTools 出现,然后加载您的页面。

using System;
using System.Threading;
using System.Threading.Tasks;
using CefSharp;
using CefSharp.WinForms;

public static class ChromiumWebBrowserExtensions
{
    public static async Task ShowDevToolsAsync(
        this ChromiumWebBrowser browser,
        CancellationToken cancellationToken)
    {
        browser.ShowDevTools();

        while (true)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // Detect if console is open
            var result = await browser.EvaluateScriptAsync(@"
(function(){
    // Inspired by https://stackoverflow.com/a/7809413/3063273
    var detector = function(){};
    detector.isOpened = false;
    detector.toString = function(){
        this.isOpened = true;
    };
    console.log('%c', detector);
    return detector.isOpened;
})()
", timeout: TimeSpan.FromSeconds(1));
            if (!result.Success)
            {
                throw new Exception(result.Message);
            }
            if (!(result.Result is bool isOpened))
                continue;
            if (isOpened)
                break;
            await Task.Delay(TimeSpan.FromMilliseconds(100), cancellationToken);
        }
    }
}

示例用法(使用我上面没有显示的附加扩展方法,但您应该了解要点):

public async Task DemonstrateAsync(ChromiumWebBrowser browser, CancellationToken cancellationToken)
{
    // Give DevTools something to hook into
    await browser.LoadDataUrlAsync("<html>Waiting for DevTools to load...</html>", cancellationToken);

    // Show DevTools and wait until it's up
    await browser.ShowDevToolsAsync(cancellationToken);

    // Give the Javascript debugger a breakpoint
    await browser.LoadDataUrlAsync("<html><script>debugger;</script></html>", cancellationToken);
}

编辑:添加异步延迟以减少循环的迭代次数while。100ms 是一个任意数字,对我来说,它可以将迭代次数从 >300 减少到 ~3。


推荐阅读