Introduction
Installation
Guides
- Engine
- Profile
- Browser
- BrowserView
- Navigation
- Content
- Context menu
- DOM
- JavaScript
- Pop-ups
- Dialogs
- Downloads
- Chrome extensions
- Network
- Cache
- Cookies
- Proxy
- Authentication
- Permissions
- Plugins
- Printing
- Passwords
- User data profiles
- Credit cards
- Media
- Zoom
- Spell checker
- Deployment
- Chromium
Troubleshooting
- Logging
- Common exceptions
- Application does not terminate
- Video does not play
- Cannot sign in to Google account
- User data is not stored
- Color scheme
- Startup failure
- Slow startup on Windows
- Unresponsive .NET Application
- Unexpected Chromium process termination
- Unexpected behavior
- Windows 7/8/8.1 end of support
Migration
Engine
This guide describes how to create, use, and close Engine
.
Refer to Architecture guide for information on how DotNetBrowser architecture is designed and works as well as main components it provides.
Creating an engine
To create a new IEngine
instance, use the EngineFactory.Create()
or the EngineFactory.Create(EngineOptions)
static methods. The method overload with EngineOptions
initializes and runs the Chromium engine with the passed options.
IEngine engine = EngineFactory.Create(engineOptions);
Dim engine As IEngine = EngineFactory.Create(engineOptions)
Depending on the hardware performance, the initialization process might take several seconds. We recommend that you do not call this method in the application UI thread because it might freeze the whole application for a while. Please use the approach described in the example.
When a new IEngine
instance is created, DotNetBrowser performs the following actions:
- Checks the environment and makes sure that it is a supported one.
- Finds the Chromium binaries and extracts them to the required directory if necessary.
- Runs the main process of the Chromium engine.
- Establishes the IPC connection between .NET and the Chromium main process.
Engine options
This section highlights major Engine options you can customize.
Rendering mode
This option indicates how the content of a web page is rendered. DotNetBrowser supports the following rendering modes:
- hardware-accelerated
- off-screen
Hardware-accelerated mode
Chromium renders the content using GPU and displays it directly on a surface. See the code sample below:
IEngine engine = EngineFactory.Create(RenderingMode.HardwareAccelerated);
Dim engine As IEngine = EngineFactory.Create(RenderingMode.HardwareAccelerated)
Read more about hardware accelerated rendering mode, its performance, and limitations.
Off-screen mode
Chromium renders the content using GPU and copies the pixels to RAM. See the code sample below:
IEngine engine = EngineFactory.Create(RenderingMode.OffScreen);
Dim engine As IEngine = EngineFactory.Create(RenderingMode.OffScreen)
Read more about off-screen rendering mode, its performance, and limitations.
Language
This option configures the language used on the default error pages and message dialogs. By default, the language is dynamically configured according to the default locale of your .NET application. If the list of supported languages does not contain the language obtained from the .NET application locale, American English is used.
Current option allows to override the default behavior and configure the Chromium engine with the given language. See the code sample below:
IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
Language = DotNetBrowser.Ui.Language.German
}.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With
{
.Language = DotNetBrowser.Ui.Language.German
}.Build())
In the code sample above, we configure the IEngine
with the German language. If DotNetBrowser fails to load a web page, the error page in German is displayed:
User data directory
Represents an absolute path to the directory containing the profiles and their data such as cache, cookies, history, GPU cache, local storage, visited links, web data, spell checking dictionary files, and so on. See the code sample below:
IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
UserDataDirectory = @"C:\Users\Me\DotNetBrowser"
}.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With
{
.UserDataDirectory = "C:\Users\Me\DotNetBrowser"
}.Build())
Same user data directory cannot be used simultaneously by multiple IEngine
instances running in a single or different .NET applications. The IEngine
creation fails if the directory is already used by another IEngine
.
If you do not provide the user data directory path, DotNetBrowser creates and uses a temp directory in the user’s temp folder.
Incognito
This option indicates whether incognito mode for the default profile is enabled. In this mode, the user data such as browsing history, cookies, site data, and the information entered in the forms on the web pages is stored in the memory. It will be released once you delete Profile
or dispose the IEngine
.
By default, incognito mode is disabled.
The following example demonstrates how to enable incognito mode:
IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
IncognitoEnabled = true
}.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With
{
.IncognitoEnabled = true
}.Build())
Intercept request per URI scheme
The Schemes
option can be used to configure the URL request interception per scheme. Here is how to configure it to intercept and handle all the requests for the custom URI schemes:
Handler<InterceptRequestParameters, InterceptRequestResponse> handler =
new Handler<InterceptRequestParameters, InterceptRequestResponse>(p =>
{
UrlRequestJobOptions options = new UrlRequestJobOptions
{
Headers = new List<HttpHeader>
{
new HttpHeader("Content-Type", "text/html", "charset=utf-8")
}
};
UrlRequestJob job = p.Network.CreateUrlRequestJob(p.UrlRequest, options);
Task.Run(() =>
{
// The request processing is performed in a worker thread
// in order to avoid freezing the web page.
job.Write(Encoding.UTF8.GetBytes("Hello world!"));
job.Complete();
});
return InterceptRequestResponse.Intercept(job);
});
EngineOptions engineOptions = new EngineOptions.Builder
{
Schemes =
{
{ Scheme.Create("myscheme"), handler }
}
}.Build();
using (IEngine engine = EngineFactory.Create(engineOptions))
{
using (IBrowser browser = engine.CreateBrowser())
{
NavigationResult result =
browser.Navigation.LoadUrl("myscheme://test1").Result;
// If the scheme handler was not set, the LoadResult would be
// LoadResult.Stopped.
// However, with the scheme handler, the web page is loaded and
// the result is LoadResult.Completed.
Console.WriteLine($"Load result: {result.LoadResult}");
Console.WriteLine($"HTML: {browser.MainFrame.Html}");
}
}
Dim interceptRequestHandler =
New Handler(Of InterceptRequestParameters, InterceptRequestResponse)(
Function(p)
Dim options = New UrlRequestJobOptions With {
.Headers = New List(Of HttpHeader) From {
New HttpHeader("Content-Type", "text/html",
"charset=utf-8")
}
}
Dim job As UrlRequestJob =
p.Network.CreateUrlRequestJob(p.UrlRequest, options)
Task.Run(Sub()
' The request processing is performed in a worker thread
' in order to avoid freezing the web page.
job.Write(Encoding.UTF8.GetBytes("Hello world!"))
job.Complete()
End Sub)
Return InterceptRequestResponse.Intercept(job)
End Function)
Dim engineOptionsBuilder = new EngineOptions.Builder
With engineOptionsBuilder
.Schemes.Add(Scheme.Create("myscheme"), interceptRequestHandler)
End With
Dim engineOptions = engineOptionsBuilder.Build()
Using engine As IEngine = EngineFactory.Create(engineOptions)
Using browser As IBrowser = engine.CreateBrowser()
Dim result As NavigationResult =
browser.Navigation.LoadUrl("myscheme://test1").Result
' If the scheme handler was not set, the LoadResult would be
' LoadResult.Stopped.
' However, with the scheme handler, the web page is loaded and
' the result is LoadResult.Completed.
Console.WriteLine($"Load result: {result.LoadResult.ToString()}")
Console.WriteLine($"HTML: {browser.MainFrame.Html}")
End Using
End Using
Head to our repository for the complete example: C#, VB.NET.
The same approach can be used to intercept and handle all HTTPS requests.
Not all schemes can be intercepted. For example, it is not possible to intercept schemes such as chrome
, data
, or chrome-extensions
. The attempt to intercept them might lead to unexpected behavior or crash inside Chromium.
In addition, some schemes are treated as local schemes, e.g. file
. They cannot be intercepted because it is not a network request.
If the specified scheme cannot be intercepted, the corresponding exception will be thrown by the EngineOptions
builder. For example: “The “file” scheme cannot be intercepted.”
User agent
Using this option you can configure the default user agent string. See the code sample below:
IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
UserAgent = "<user-agent>"
}.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With
{
.UserAgent = "<user-agent>"
}.Build())
You can override the default user agent string in each IBrowser
instance.
Remote debugging port
This option allows to enable the Chrome Developer Tools (or DevTools) remote debugging. The following example demonstrates how to use this feature:
IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
ChromiumSwitches = { "--remote-allow-origins=http://localhost:9222" },
RemoteDebuggingPort = 9222
}.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With
{
.ChromiumSwitches = { "--remote-allow-origins=http://localhost:9222" },
.RemoteDebuggingPort = 9222
}.Build())
Since Chromium 111, it is required to specify remote-allow-origins
switch to allow web socket connections from specified origin. More information in Issue 1422444.
Now you can load the remote debugging URL in an IBrowser
instance to open the DevTools page to inspect HTML, debug JavaScript, and others. See an example below:
Do not open the remote debugging URL in other web browser applications such as Mozilla Firefox, Microsoft Internet Explorer, Safari, Opera, and others as it can result in a native crash in Chromium DevTools web server.
The remote debugging feature is compatible only with the Chromium version used by DotNetBrowser library. For example, if you use DotNetBrowser 3.0.0 based on Chromium 131.0.6778.70, you can open the remote debugging URL only in the same Chromium/Google Chrome. If you use previous DotNetBrowser version, you need to download the corresponding Chromium build.
We recommend loading the remote debugging URL in an IBrowser
instance instead of Google Chrome.
Disabling touch menu
Long press on Windows 10 touch devices may show the following touch menu:
The code sample below demonstrates how to disable this touch menu:
IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
TouchMenuDisabled = true
}.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With
{
.TouchMenuDisabled = true
}.Build())
Chromium binaries directory
Use this option to define an absolute or relative path to the directory where the Chromium binaries are located or should be extracted to. See the code sample below:
IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
ChromiumDirectory = @"C:\Users\Me\.DotNetBrowser\chromium"
}.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With
{
.ChromiumDirectory = @"C:\Users\Me\.DotNetBrowser\chromium"
}.Build())
For details, refer to Chromium Binaries Location section.
Autoplaying videos
To enable autoplay of video content on the web pages, use the option below:
IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
AutoplayEnabled = true
}.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With
{
.AutoplayEnabled = true
}.Build())
Chromium switches
Use this option to define the Chromium switches passed to the Chromium main process. See the code sample below:
IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
ChromiumSwitches = { "--<switch-name>", "--<switch-name>=<switch-value>" }
}.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With
{
.ChromiumSwitches = { "--<switch-name>", "--<switch-name>=<switch-value>" }
}.Build())
Not all the Chromium switches are supported by DotNetBrowser, so there is no guarantee that the passed switches will work and will not cause any errors. We recommend configuring Chromium through the Engine Options instead of switches.
Google APIs
Some Chromium features such as Geolocation, Spelling, Speech, and others use Google APIs. To access those APIs, an API Key, OAuth 2.0 client ID, and client secret are required. To acquire the API Key, follow these instructions.
To provide the API Key, client ID, and client secret, use the following code sample:
IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
GoogleApiKey = "<api-key>",
GoogleDefaultClientId = "<client-id>",
GoogleDefaultClientSecret = "<client-secret>"
}.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With
{
.GoogleApiKey = "<api-key>",
.GoogleDefaultClientId = "<client-id>",
.GoogleDefaultClientSecret = "<client-secret>"
}.Build())
Setting up API keys is optional. However, if this is not done, some APIs using Google services fail to work.
Geolocation
Geolocation is one of Chromium features using Google API. You must enable Google Maps Geolocation API and billing, otherwise, Geolocation API fails to work. Once you enable Google Maps Geolocation API and billing, you can provide the keys to DotNetBrowser Chromium engine.
To enable geolocation in DotNetBrowser, grant a specific permission.
Voice recognition
Voice recognition is one of those Chromium features that uses Google API. You must enable Speech API and billing, otherwise voice recognition does not work.
Once you enable Speech API and billing, you can provide the keys to DotNetBrowser Chromium engine.
Engine dispose
The IEngine
instance allocates memory and system resources that must be released. When the IEngine
is no longer needed, it must be disposed through the IEngine.Dispose()
method to shutdown the native Chromium process and free all the allocated memory and system resources. See the example below:
IEngine engine = EngineFactory.Create();
// ...
engine.Dispose();
Dim engine As IEngine = EngineFactory.Create()
' ...
engine.Dispose()
Any attempt to use an already disposed IEngine
will lead to the ObjectDisposedException
.
To check whether the IEngine
is disposed, use the IsDisposed
property shown in the code sample below:
bool disposed = engine.IsDisposed;
Dim disposed As Boolean = engine.IsDisposed
Engine events
Engine disposed
To get notifications when the IEngine
is disposed, use the Disposed
event shown in the code sample below:
engine.Disposed += (s, e) => {};
AddHandler engine.Disposed, Sub(s, e)
End Sub
Engine crashed
To get notifications when the IEngine
unexpectedly crashes due to an error inside the Chromium engine, use the approach shown in the code sample below:
engine.Disposed += (s, e) =>
{
long exitCode = e.ExitCode;
// The engine has been crashed if this exit code is non-zero.
});
AddHandler engine.Disposed, Sub(s, e)
Dim exitCode As Long = e.ExitCode
' The engine has been crashed if this exit code is non-zero.
End Sub)