CefSharp.Dom is a fork of puppeteer-sharp by Darío Kondratiuk that has been adapted specifically for use with CefSharp.
- Strongly typed async DOM API
- Direct communication with the ChromiumWebBrowser instance rather than opening a web socket.
- 1:1 mapping of DevToolsContext and ChromiumWebBrowser
- CEF only supports a subset of features, features will be added/removed as the project matures
- .Net 4.7.2 or .Net Core 3.1 or greater
- CefSharp 104.4.180 or greater
If you have an issue or a question:
- Ask a question on Discussions.
See this document for information on how to contribute.
The DevToolsContext class is the main entry point into the library and can be created from a ChromiumWebBrowser instance. Only a single DevToolsContext should exist at any given time, when you are finished them make sure you dispose via DisposeAsync. Starting in version 2.x the DevToolsContext multiple calls to CreateDevToolsContextAsync will return the same instance per ChromiumWebBrowser and will be Disposed when the ChromiumWebBrowser is Disposed. If you need to use the DevToolsContext in multiple places in your code, calling CreateDevToolsContextAsync is now supported without dispoing. If the DevToolsContext is disposed then calls to CreateDevToolsContextAsync will create a new instance.
// Add using CefSharp.Dom; to get access to the// CreateDevToolsContextAsync extension methodvardevtoolsContext=awaitchromiumWebBrowser.CreateDevToolsContextAsync();// Manually dispose of context (prefer DisposeAsync as the whole API is async)awaitdevToolsContext.DisposeAsync();// Dispose automatically via await using// https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-disposeasync#using-async-disposableawaitusingvardevtoolsContext=awaitchromiumWebBrowser.CreateDevToolsContextAsync();Read/write to the DOM
// Add using CefSharp.Dom to access CreateDevToolsContextAsync and related extension methods.awaitusingvardevToolsContext=awaitchromiumWebBrowser.CreateDevToolsContextAsync();awaitdevToolsContext.GoToAsync("http://www.google.com");// Get element by Id// https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorvarelement=awaitdevToolsContext.QuerySelectorAsync<HtmlElement>("#myElementId");//Strongly typed element types (this is only a subset of the types mapped)varhtmlDivElement=awaitdevToolsContext.QuerySelectorAsync<HtmlDivElement>("#myDivElementId");varhtmlSpanElement=awaitdevToolsContext.QuerySelectorAsync<HtmlSpanElement>("#mySpanElementId");varhtmlSelectElement=awaitdevToolsContext.QuerySelectorAsync<HtmlSelectElement>("#mySelectElementId");varhtmlInputElement=awaitdevToolsContext.QuerySelectorAsync<HtmlInputElement>("#myInputElementId");varhtmlFormElement=awaitdevToolsContext.QuerySelectorAsync<HtmlFormElement>("#myFormElementId");varhtmlAnchorElement=awaitdevToolsContext.QuerySelectorAsync<HtmlAnchorElement>("#myAnchorElementId");varhtmlImageElement=awaitdevToolsContext.QuerySelectorAsync<HtmlImageElement>("#myImageElementId");varhtmlTextAreaElement=awaitdevToolsContext.QuerySelectorAsync<HtmlImageElement>("#myTextAreaElementId");varhtmlButtonElement=awaitdevToolsContext.QuerySelectorAsync<HtmlButtonElement>("#myButtonElementId");varhtmlParagraphElement=awaitdevToolsContext.QuerySelectorAsync<HtmlParagraphElement>("#myParagraphElementId");varhtmlTableElement=awaitdevToolsContext.QuerySelectorAsync<HtmlTableElement>("#myTableElementId");// Get a custom attribute valuevarcustomAttribute=awaitelement.GetAttributeAsync<string>("data-customAttribute");//Set innerText property for the elementawaitelement.SetInnerTextAsync("Welcome!");//Get innerText property for the elementvarinnerText=awaitelement.GetInnerTextAsync();//Get all child elementsvarchildElements=awaitelement.QuerySelectorAllAsync("div");//Change CSS style background colourawaitelement.EvaluateFunctionAsync("e => e.style.backgroundColor = 'yellow'");//Type text in an input fieldawaitelement.TypeAsync("Welcome to my Website!");//Click The elementawaitelement.ClickAsync();// Simple way of chaining method calls together when you don't need a handle to the HtmlElementvarhtmlButtonElementInnerText=awaitdevToolsContext.QuerySelectorAsync<HtmlButtonElement>("#myButtonElementId").AndThen(x =>x.GetInnerTextAsync());//Event Handler//Expose a function to javascript, functions persist across navigations//So only need to do this onceawaitdevToolsContext.ExposeFunctionAsync("jsAlertButtonClick",()=>{_=devToolsContext.EvaluateExpressionAsync("window.alert('Hello! You invoked window.alert()');");});varjsAlertButton=awaitdevToolsContext.QuerySelectorAsync<HtmlButtonElement>("#jsAlertButton");//Write up the click event listner to call our exposed function_=jsAlertButton.AddEventListenerAsync("click","jsAlertButtonClick");//Get a collection of HtmlElementsvardivElements=awaitdevToolsContext.QuerySelectorAllAsync<HtmlDivElement>("div");foreach(vardivindivElements){// Get a reference to the CSSStyleDeclarationvarstyle=awaitdiv.GetStyleAsync();//Set the border to 1px solid redawaitstyle.SetPropertyAsync("border","1px solid red",important:true);awaitdiv.SetAttributeAsync("data-customAttribute","123");awaitdiv.SetInnerTextAsync("Updated Div innerText");}//Using standard arrayvartableRows=awaithtmlTableElement.GetRowsAsync().ToArrayAsync();foreach(varrowintableRows){varcells=awaitrow.GetCellsAsync().ToArrayAsync();foreach(varcellincells){varnewDiv=awaitdevToolsContext.CreateHtmlElementAsync<HtmlDivElement>("div");awaitnewDiv.SetInnerTextAsync("New Div Added!");awaitcell.AppendChildAsync(newDiv);}}//Get a reference to the HtmlCollection and use async enumerable//Requires Net Core 3.1 or highervartableRowsHtmlCollection=awaithtmlTableElement.GetRowsAsync();awaitforeach(varrowintableRowsHtmlCollection){varcells=awaitrow.GetCellsAsync();awaitforeach(varcellincells){varnewDiv=awaitdevToolsContext.CreateHtmlElementAsync<HtmlDivElement>("div");awaitnewDiv.SetInnerTextAsync("New Div Added!");awaitcell.AppendChildAsync(newDiv);}}//Wait for Initial page loadawaitchromiumWebBrowser.WaitForInitialLoadAsync();awaitusingvardevtoolsContext=awaitchromiumWebBrowser.CreateDevToolsContextAsync();awaitdevtoolsContext.SetContentAsync("<div>My Receipt</div>");varresult=awaitdevtoolsContext.GetContentAsync();awaitusingvardevtoolsContext=awaitchromiumWebBrowser.CreateDevToolsContextAsync();varseven=awaitdevtoolsContext.EvaluateExpressionAsync<int>("4 + 3");varsomeObject=awaitdevtoolsContext.EvaluateFunctionAsync<dynamic>("(value) => ({a: value})",5);Console.WriteLine(someObject.a);//Wait for Initial page loadawaitchromiumWebBrowser.WaitForInitialLoadAsync();awaitusingvardevToolsContext=awaitchromiumWebBrowser.CreateDevToolsContextAsync();awaitdevToolsContext.ScreenshotAsync("file.png");// Set ViewportawaitDevToolsContext.SetViewportAsync(newViewPortOptions{Width=500,Height=500});Currently not supported via CefSharp.Dom, use ChromiumWebBrowser.PrintToPdfAsync instead.