После некоторых неудачных попыток мой метод расширения ShowDevToolsAsync
, показанный ниже, работает надежно.
Примечание. Я использую модификацию https://stackoverflow.com/a/7809413/3063273, чтобы определить, когда DevTools завершил загрузку.Я не уверен, что будет более надежной альтернативой.Возможно, вы могли бы подключиться к ILoadHandler.OnFrameLoadEnd
, как предлагают комментарии к ОП, и работать оттуда.Я пробовал этот путь, но не смог пройти достаточно далеко, прежде чем смог заставить работать это решение, которое я считаю более прямым и очевидным.
Важно : ваш экземпляр ChromiumWebBrowser
необходимо уже загрузить веб-страницу (или, по крайней мере, начать загружать ее), иначе 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
.100 мс - это произвольное число, которое для меня уменьшило число итераций с> 300 до ~ 3.