Дождитесь загрузки DevTools - PullRequest
0 голосов
/ 19 июня 2019

Как я могу определить, когда DevTools завершил загрузку?

В CefSharp вы можете открыть окно DevTools с помощью метода расширения ShowDevTools().Я хочу дать указание встроенному браузеру загружать страницу только после загрузки DevTools (в частности, после того, как он подключил свой отладчик JavaScript).Однако ShowDevTools(), кажется, выполняется асинхронно.

1 Ответ

0 голосов
/ 26 июня 2019

После некоторых неудачных попыток мой метод расширения ShowDevToolsAsync, показанный ниже, работает надежно.

Примечание. Я использую модификацию https://stackoverflow.com/a/7809413/3063273, чтобы определить, когда DevTools завершил загрузку.Я не уверен, что будет более надежной альтернативой.Возможно, вы могли бы подключиться к ILoadHandler.OnFrameLoadEnd, как предлагают комментарии к ОП, и работать оттуда.Я пробовал этот путь, но не смог пройти достаточно далеко, прежде чем смог заставить работать это решение, которое я считаю более прямым и очевидным.

Важно : ваш экземпляр ChromiumWebBrowser необходимо уже загрузить веб-страницу (или, по крайней мере, начать загружать ее), иначе DevTools никогда не зацепится за нее, а просто будет сидеть с таким сообщением:

DevTools was disconnected from the page

Если вы хотите убедиться, что 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.100 мс - это произвольное число, которое для меня уменьшило число итераций с> 300 до ~ 3.

...