Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cefsharp initializing for the second time throws error

My application needs to invoke (off screen) browser on request and cleanup once it is done.

So I created an offscreen browser

 public class OffScreenBrowser 
{
    private static ChromiumWebBrowser _browser;

    private static CefSettings _settings;

    public void Load(string url,System.Drawing.Size size)
    {
        if (Cef.IsInitialized) return;
        Init(new BrowserProcessHandler());

        _browser = new ChromiumWebBrowser(url) {Size = size};
        _browser.NewScreenshot += _browser_NewScreenshot;
    }
    public System.Windows.Controls.Image BrowserImage { get; set; }
    public Action NewScreenShotAction { get; set; }

    private void _browser_NewScreenshot(object sender, EventArgs e)
    {
        var bitmap = _browser.ScreenshotOrNull();
        Application.Current.Dispatcher.Invoke(new Action(() =>
        {
            using (MemoryStream memory = new MemoryStream())
            {
                bitmap.Save(memory, ImageFormat.Png);
                memory.Position = 0;
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.StreamSource = memory;
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.EndInit();

                BrowserImage = new System.Windows.Controls.Image() {Source = bitmapImage};
                NewScreenShotAction();
            }
        }));
    }

    public void Close()
    {
        _browser.NewScreenshot -= _browser_NewScreenshot;
        _browser.Dispose();
        _settings.Dispose();
        Cef.Shutdown();
    }

    public static void Init(IBrowserProcessHandler browserProcessHandler)
    {
        _settings = new CefSettings();
        if (!Cef.Initialize(_settings, true, browserProcessHandler))
            throw new Exception("Unable to Initialize Cef");
    }
}

The idea is-on clicking a button create browser and on clicking another button close the browser

private OffScreenBrowser offScreenBrowser;

private void OPen_OnClick(object sender, RoutedEventArgs e)
{
    var address = @"https://www.google.co.uk";
    var width = 200;
    var height = 100;
    var windowSize = new System.Drawing.Size(width, height);
     offScreenBrowser = new OffScreenBrowser();
    offScreenBrowser.Load(address, windowSize);

    offScreenBrowser.NewScreenShotAction = () => 
    {
        Browser.Content = offScreenBrowser.BrowserImage;
    };
}

private void Close_OnClick(object sender, RoutedEventArgs e)
{
    offScreenBrowser.Close();
}

On the first click it all works fine. On clicking close it seems like the cleanup is fine.

But when I click the open button for the second time I am getting an exception as below

"An unhandled exception of type 'System.AccessViolationException' occurred in CefSharp.Core.dll

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

What am I doing wrong?

like image 415
Jimmy Avatar asked Jul 15 '26 10:07

Jimmy


2 Answers

This is a limitation in Chromium framework.

CEF can only be Initialized/Shutdown once per process, See Need to Know/Limitations for more details, this is a limitation of the underlying Chromium framework.

like image 198
MouadRoZal Avatar answered Jul 18 '26 00:07

MouadRoZal


In my case I had a similar situation. But for me, I just needed the same app to have multiple instances so that it can be runned in different screens at the same time.

The solution I found is really simple; you just need to change the "RootCachePath" on CefSettings. The reason for this is that the cache path of each instance cannot be the same.

Finally, I delete the folder created for this purpose when the app is closed.

Here an example:

    Program.rootPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + Program.rootPath + DateTime.Now.Ticks;
    
    CefSettings settings = new CefSettings();
    settings.IgnoreCertificateErrors = true;
    settings.RootCachePath = Program.rootPath;
    Cef.Initialize(settings);

    browser = new ChromiumWebBrowser(url);
like image 28
Ander De Santos Avatar answered Jul 18 '26 00:07

Ander De Santos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!