Skip to content

SelfHost BrowserSubProcess

PracticeMedicine edited this page Jul 7, 2024 · 5 revisions

CefSharp uses the same multiprocess model as Chromium. When you launch an application that embeds CefSharp then by default you will see multiple instances of CefSharp.BrowserSubProcess.exe in Task Manager.

It is possible and in some cases required that you Self Host the BrowserSubProcess. Self Host means that multiple instances of your application exe will be launched instead of CefSharp.BrowserSubProcess.exe.

General

  • You MUST set performDependencyCheck to false.
  • Add an Application Manifest to your exe if you don't already have one, it's required for Windows 10 compatibility, GPU detection, HighDPI support and tooltips. You can review the CefSharp.BrowserSubProcess.exe app.manifest for a working example.
  • For .Net Core 3.1/5/6/7 when Publishing a Single file you must Self Host.
  • Better user experience when it comes to firewall permission prompts.
  • DPI Awareness will match that of your application.
  • 32bit executables should be made LargeAddressAware. See also https://github.com/cefsharp/CefSharp/wiki/General-Usage#win32-out-of-memory
  • For 64bit executables increasing the Stack Size to 8mb to match Chromium is recommended.
  • If running on Terminal Server then make your application TSAware

WinForms

Self Hosting using WinForms is very easy, for x64/x86 build your Program.cs would look something like:

public static class Program
{
	[STAThread]
	public static int Main(string[] args)
	{
		var exitCode = CefSharp.BrowserSubprocess.SelfHost.Main(args);

		if (exitCode >= 0)
		{
			return exitCode;
		}

		var settings = new CefSettings()
		{
			//By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
			CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache"),
			BrowserSubprocessPath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName
		};

		//Perform dependency check to make sure all relevant resources are in our output directory.
		//IMPORTANT: MUST set performDependencyCheck false
		Cef.Initialize(settings, performDependencyCheck: false, browserProcessHandler: null);

		var browser = new BrowserForm();
		Application.Run(browser);

		return 0;
	}
}

WPF

For WPF there are a few steps required as the compiler generates the Main method for you. You need to:

  • Create your own custom entry point (typically adding a Program.cs file with a static Main method) that calls Application.Run
  • Change the <StartupObject/> to use your own main method, (Right click Properties on your project, Startup Object is a dropdown or edit your proj file manually).

Your proj file should look something like:

<PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UseWPF>true</UseWPF>
    <StartupObject>MyApp.Program</StartupObject>
</PropertyGroup> 

For x64/x64 build your Program.cs would look something like:

namespace MyApp
{
	public static class Program
	{
		[STAThread]
		public static int Main(string[] args)
		{
			var exitCode = CefSharp.BrowserSubprocess.SelfHost.Main(args);

			if (exitCode >= 0)
			{
				return exitCode;
			}

			var settings = new CefSettings()
			{
				//By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
				CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache"),
				BrowserSubprocessPath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName
			};

			//IMPORTANT: MUST set performDependencyCheck false
			Cef.Initialize(settings, performDependencyCheck: false, browserProcessHandler: null);

			var app = new App();
			app.InitializeComponent();
			return app.Run();
		}
	}
}