-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Trouble Shooting
For a better understanding of CefSharp
please start by reading the General Usage Guide, it covers a range of topics. The General Usage#Need to know/Limitations section has a list of important facts.
By default CEF
has it's own log file, Debug.log
which is located in your executing folder. e.g. bin
. You can change the path/filename of this log file
var settings = new CefSettings()
{
LogFile = "Debug.log", //You can customise this path
LogSeverity = LogSeverity.Default // You can change the log level
};
//Perform dependency check to make sure all relevant resources are in our output directory.
Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
1) Platform Target
Version 51.0.0
added support for the AnyCPU
target, see https://github.com/cefsharp/CefSharp/issues/1714 for details. You can still of course select either x86 or x64 when using the NuGet
packages (This is the simplest option). You need to change the Solution Target
as this is a current limitation (changing at just the project level is not enough). Pull requests welcome with improvements.
2) Dependencies still not showing up after adding the Nuget
packages?
Follow the Post Installation
instructions provided in the Nuget Readme.txt (This file would have been opened when you installed the packages).
https://github.com/cefsharp/CefSharp/blob/master/NuGet/Readme.txt#L7
A complex set of dependencies are required, these must be distributed with your application.
https://github.com/cefsharp/CefSharp/wiki/Output-files-description-table-%28Redistribution%29
TODO: ClickOnce (VS Installer) requires additional steps
Before instances of ChromiumWebBrowser
are created the underlying framework needs to be initialized. If you don't need to configure any settings then this will be done automatically for you by the framework. See https://github.com/cefsharp/CefSharp/wiki/General-Usage#initialize-and-shutdown for more details.
Should you need to specify some settings, like a CachePath
(so the browser persists cookies, etc) then you'll need to manually initialize. In essence however it boils down to creating a settings object, ensuring that the browser sub process property is set correctly, then calling the main initialization function using these settings.
The following code will do this for you:
//Set the cache path
var settings = new CefSettings() { CachePath = "Cache" };
//Perform dependency check to make sure all relevant resources are in our output directory.
Cef.Initialize(settings , performDependencyCheck: true, browserProcessHandler: null);
Remember to also include the relevant using statements, see below for examples.
using CefSharp;
using CefSharp.Wpf;
using CefSharp;
using CefSharp.WinForms;
using CefSharp;
using CefSharp.OffScreen;
1) Where are you calling the initial invocation of the browser?
If you need to have the browser not display at startup, then you simply need to pass in an empty string when creating the object, and all you'll receive is a blank browser window.
This simple WinForms
demo shows how to do this correctly, using the following bit of code:
browser = new ChromiumWebBrowser("www.google.com");
toolStripContainer.ContentPanel.Controls.Add(browser);
Replace the 'www.google.com' string with something like 'string.Empty' if you don't want to load anything initially.
You'll notice in the above example, that the browser is loaded into a 'toolStripContainer' this is also an important point to note, and is covered in the next check point.
2) Where are you trying to render the browser?
There are many examples out there on the internet that show the browser being added to an application's window by adding it directly to the controls collection of the form.
In the older versions of CefSharp this was the main accepted way of doing things, and on the whole of it this does still work.
However, in some edge cases when doing things this way the browser does not render correctly, often re-appearing when the form is re-sized leading to the belief that the problem cause is actually point number 2 above.
It's therefore recommended that you render the browser into a WinForms
panel or similar object, there are two very good reasons for this.
a) The panel allows you to control the browser size, it will never overflow a panel component, but if attached to a form will attempt to use the full form surface often appearing behind regular win-form controls.
b) You can hide the browser (For example if you didn't want to show it at start up) by simply hiding the panel
Rendering into a common component gives you much more control over the render surface allowing you to do many more things not possible when adding direct to the forms controls.
You need to modify your app.manifest
to include a dependency on Microsoft.Windows.Common-Controls
like in the WinForms
example app: https://github.com/cefsharp/CefSharp/blob/master/CefSharp.WinForms.Example/app.manifest#L15
Moved to FAQ WPF blurry rendering.
GPU acceleration is on by default. This creates a dependency on graphics cards and their drivers, which are notoriously unreliable. If you experience slow or quirky rendering, try:
- Disable GPU acceleration (see below)
- Disable GPU VSync (see below)
- Confirm the command line args have filtered through by starting your app and navigating to this URL:
chrome://version
- Try your app on a different machine, preferably with a different video card.
- Open
chrome://gpu/
inChrome
to see what it says about yourGPU
.
var settings = new CefSettings();
settings.CefCommandLineArgs.Add("disable-gpu"); // Disable GPU acceleration
settings.CefCommandLineArgs.Add("disable-gpu-vsync"); //Disable GPU vsync
Cef.Initialize(settings);
No-nos:
- Do not create
COM
objects on CEF callback threads. This will cause shutdown to freeze. - If you call
Cef.Shutdown()
explicitly, do not do so on a background thread - this may cause a freeze. It must be called on the main application thread (UI Thread). - Calling
Application.Exit()
and thenEnvironment.Exit()
will cause a hang - just wait forApplication.Exit()
to finish.
Things to try:
- Call
Cef.Initialize()
very early in your application, rather than letting it be called by the first browser control you create. - Use WinDbg to diagnose what is causing the hang: https://github.com/cefsharp/CefSharp/issues/872#issuecomment-82978118
Related issues:
- https://github.com/cefsharp/CefSharp/issues/820
- https://github.com/cefsharp/CefSharp/issues/872
- https://github.com/cefsharp/CefSharp/issues/990
This section covers debugging and diagnosing native/unmanaged crashes in libcef.dll, BrowserSubProcess, and C++ code in general. When these crashes occur, the C# exception handler does not get called and your application exits. Windows logs an Error event, which you can find the details of using Windows Event Viewer. CEF
also has it's own log file, which by default is called Debug.log
, it will be in your applications executing directory e.g. bin
directory.
CEF
supports the Crashpad crash-reporting system. For generic CEF
details on configuring see https://bitbucket.org/chromiumembedded/cef/wiki/CrashReporting.md
- Disabled by default
- Provides many options including creating crash dumps to a folder or server
- crash_reporter.cfg needs to be placed next to your main application executable.
-
Make sure you set
ExternalHandler=CefSharp.BrowserSubprocess.exe
otherwise you main application executable will be used (which is supported, just requires additional code in your application)
Example crash_reporter.cfg which generates crash dumps in the "C:\Users\[CurrentUser]\AppData\Local\[AppName]\User Data
folder.
# Crash reporting is configured using an INI-style config file named
# "crash_reporter.cfg". This file must be placed next to
# the main application executable.
# Comments start with a hash character and must be on their own line.
# See https://bitbucket.org/chromiumembedded/cef/wiki/CrashReporting.md
# for further details
[Config]
ProductName=CefSharp.MinimalExample.WinForms
ProductVersion=1.0.0
AppName=CefSharp.MinimalExample
ExternalHandler=CefSharp.BrowserSubprocess.exe
Load one of the following URLs in a ChromiumWebBrowser
instance to cause a crash:
- Main (browser) process crash:
chrome://inducebrowsercrashforrealz
- Renderer process crash:
chrome://crash
- GPU process crash:
chrome://gpucrash
- Out of memory:
chrome://memory-exhaust/
To obtain a meaningful stack trace you need to load the relevant pdb
files.
For crashes in libcef.dll
- Download the Release Symbols that match the
CEF
version you're using from https://cef-builds.spotifycdn.com/index.html - Extract
libcef.dll.pdb
into the executing folder (the same directory aslibcef.dll
).
To identity the CEF
version use one of the following options:
- Check the Release Notes here on
GitHub
. - You can also open
chrome://version
in the browser to determine the version. - Check your
packages.config
file, look for thecef.redist.x86
package, it's version will be something like79.1.36
, that's the short versionCEF
you'll need to download. The full version will look like79.1.36+g90301bd+chromium-79.0.3945.130
The CefSharp
specific symbols are included in the Nuget
packages, the pdbs
have been generated using GitLink
see #1680 for details. GitLink
provides you with the ability to step directly into the .Net source
directly from your application. If you see an exception in libcef.dll
then focus on getting the CEF
release symbols.
If you obtain a crashdump
from a users computer you can analyze it in Visual Studio
at a later point, manually loading the symbols to obtain a symbolized stack trace. If you've never analysed a crashdump
before check out https://msdn.microsoft.com/en-us/library/windows/desktop/ee416349(v=vs.85).aspx#analyzing_a_minidump there are also many other resources available on the internet.
If CefSharp.BrowserSubProcess.exe
is crashing and you can reproduce the crash on your development machine you may find it useful to attach the debugger to CefSharp.BrowserSubProcess.exe
, add the following command line option. When the message box opens, attach the debugger to the matching process (should be named Chromium Renderer
). If you have the libcef.dll.pdb
in the same folder as libcef.dll
it should load the symbols successfully an when the app crashes hopefully you will have a more detailed crash stack trace.
settings.CefCommandLineArgs.Add("renderer-startup-dialog");
See Crash Reporting
section above for using Crashpad
.
Older versions Check the AppData\Local\CrashDumps
folder for CefSharp.BrowserSubProcess.exe
dumps. To properly analyze a crash and obtain a symbolized stack trace you will need to load debugging symbols (See above).
To manually generate a crash dump your user can utilize Procdump like this:
procdump -e -ma <binaryname or PID> <dumpfile.dmp>
If your user is on Win 8.1 or later they can use the -r
option for a bit more efficiency in creating the memory dump.
If that command line doesn't do the trick, you might need to use procdump
's -e1
option instead of -e
.
You then load the memory dump into Visual Studio or WinDbg and see what the call stack for the CEF
. (You can google about how to deal with memory dumps and .Net if you haven't done it before.) Our recommendation is to use Visual Studio 2013+ with integrated WinDbg, or WinDbg.
Mozilla - How to get a stacktrace with WinDbg
Will look something like "c:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe" -y . -c ".ecxr;k30;q" -z my_dump_file.dmp
Exception code: 0x4000001f
This is the exception code that occurs when the int 3
instruction is executed.
CEF
is known to do this when you violate its threading restrictions about what executes on which CEF
thread. See CEF Threads for the list of CEF
threads.
If you are lost as to what caused this, reproduce the crash in Visual Studio with symbols loaded.
- http://stackoverflow.com/a/14385526/4583726
- http://vadmyst.blogspot.com.au/2008/01/unmanaged-debugging-option-very-useful.html
- Capturing unhandled exceptions in a mixed native/CLR environment
- General Usage Guide - Unmanaged Exceptions
The Chromium DevTools
are available for debugging Javascript
, you can load DevTools
programatically using the chromiumWebBrowser.ShowDevTools() method (there is a corresponding chromiumWebBrowser.CloseDevTools() method also). Make sure to add using CefSharp; to your usings statements.
Make sure you call this after the browser has been initialized.
using CefSharp;
//**OffScreen**
browser.BrowserInitialized += (sender, args) =>
{
browser.ShowDevTools();
};
using CefSharp;
//**WinForms**
browser.IsBrowserInitializedChanged += (sender, args) =>
{
browser.ShowDevTools();
};
//**WinForms (alternative)**
// If you see the DevTools window flickering
// it's likely vying for focus with your form
// open DevTools on your UI Thread.
using CefSharp;
browser.IsBrowserInitializedChanged += (sender, args) =>
{
var browser = (ChromiumWebBrowser)sender;
browser.BeginInvoke((Action)delegate
{
browser.ShowDevTools();
});
};
using CefSharp;
//**WPF**
browser.IsBrowserInitializedChanged += (sender, args) =>
{
if ((bool)args.NewValue)
{
browser.ShowDevTools();
}
};
If you are new to DevTools check out the official Chrome guide at https://developers.google.com/web/tools/chrome-devtools/#beginners
-
Google Developers Memory Diagnosis (Please note that
CefSharp
doesn't have aTaskManager
, you can use theDevTools
to troubleshoot memory usage).
Ask on Gitter Chat - Make sure you provide as much detail as possible.