Jimmy
Jimmy

Reputation: 3264

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?

Upvotes: 3

Views: 5598

Answers (3)

Ander De Santos
Ander De Santos

Reputation: 11

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);

Upvotes: 1

Iyad Bacdounes
Iyad Bacdounes

Reputation: 73

to solve this you can call the Cef.Initialize in the start form and you need to call it only once in your application the you can call ChromiumWebBrowser many times inside any for of your application forms it worked for me

Upvotes: 0

MouadRoZal
MouadRoZal

Reputation: 21

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.

Upvotes: 2

Related Questions