ActiveX Wrapper Crash

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

ActiveX Wrapper Crash

Postby ecreality » Thu Nov 20, 2014 1:34 pm

First of All, sorry for my English.

We are trying to do an ActiveX Wrapper to embed Cef in our VFP(Visual FoxPro) applications and replace the old IE ActiveX, dragging visually the ActiveX control to my form and resizing and positioning where we want.


Thanks to all users of this forum and theirs code.
Thanks to http://mickeymickstechblog.blogspot.com ... oject.html, the MFC Cef Dialog Based Original example i based my work to por this example to a Dll.
Thanks to Microsoft MFCActiveX Sample, that is what i based my activex dialog and inner controls that i can "drag" visually in VFP Form, and call functions.
After merge this two projects, a lot of trys and after reading and reading a lot in this forums and other articles in the web, i do an MFC Dialog Based ActiveX thats succesfully embed Cef3 in my VFP test app.
It can "navigate" from one page to another passing the url from VFP to Dll(mimics IE ActiveX Navigate) and execute some javascripts, and work fine in my VFP Form.

But..... (Always there is a But)

The problem is that if I re-run my form with Cef3 embeded without close the process the second run crash.

I have already read from this forums that Cef cant re-initiaze on the same process, the "Global Context". However i also read that cef can reinitiaze if no browser created or cefshutdown called.

I try not call CefShutdown, or close only the browser, and also call CefQuitMessageLoop in destructor function but crash o hangs my app always except when call CefShutdown and only this.
I think the posibility of save some type of "Global Context" handler, and retrieve from my VFP and later pass this handler in the second run of Initialize and "restore GlobalContext" handler to the Dll, or something similar.

Data:
CefVersion: cef_binary_3.2171.1879_windows32
libcef_dll_wrapper recompiled with /Md (The MFC Test ActiveX that I use originally is compiled with /Md, later i will try /Mt).
I use separate process, i try with the cefsimple.exe and cefclient.exe from binary. Both work initialy and crash later.
MFC ActiveX Wrapper with 4 main classes:
one for entry point of Dll and Register functions (from COleControlModule),
one that implement the exported functions and initialize and shutdown chromiun (from COleControl),
one MFC Dialog (from CDialog) and
one really simply ClientHandler from the MFC CEF original example.

I read somewhere in this forum from another user that try to wrap Cef that his init code works in a separated function called from client app.

My Init function (I call from the Init event of my VFP Form):
Code: Select all
        AFX_MANAGE_STATE(AfxGetStaticModuleState());
   
   RECT rect;
   m_MainDialog.GetClientRect(&rect);
   
   //Create the necessary objects needed to initialize CEF
   CefMainArgs mainArgs(theApp.m_hInstance);
   
   CefSettings appSettings;
   CefBrowserSettings browserSettings;
   CefRefPtr<CefApp> cefApplication;
   CefWindowInfo info;

   CefString(&appSettings.browser_subprocess_path) = "C:/Users/Usuario/Downloads/PruebasBrowsers/cef_binary_3.2171.1879_windows32_client/Release/cefclient.exe";
   appSettings.multi_threaded_message_loop = true; //needed for MFC projects (unless we want to implement custom message-loop)   
   info.SetAsChild(m_MainDialog.GetSafeHwnd(), rect);
   
        //Sometimes crash here, getting the client
   CefRefPtr<CefClient> client;
   client  = (new ClientHandler());   
   m_Handler = (ClientHandler*)client.get();
      
   //Initialize CEF
   bool bSucceeded = true;
   if (!this->m_Handler->GetBrowserHwnd())
   {
      bSucceeded = CefInitialize(mainArgs, appSettings, cefApplication, NULL);
      AfxMessageBox(L"JUR tras initialize");
                //Try reinitialize, works.
      bSucceeded = CefInitialize(mainArgs, appSettings, cefApplication, NULL);
      AfxMessageBox(L"JUR tras re-initialize");
      if (bSucceeded)
      {
         AfxMessageBox(L"JUR exito");
         MessageBox((LPCTSTR)this->m_Handler->GetBrowserHwnd(), L"browserHwnd");
         MessageBox((LPCTSTR)this->m_Handler, L"browserHwnd");
                        //Sometimes crash here, after CreateBrowser.
         bSucceeded = CefBrowserHost::CreateBrowser(info, m_Handler, _T("http://www.google.es"), browserSettings, NULL);
      }
      AfxMessageBox(L"JUR trasexito");
   }
   
   return bSucceeded;


In the second run of form, sometimes crash in the get client zone(i debug, >libcef.dll!0fee9e10()) and sometimes after Browser create.
Control Destructor:
Code: Select all
CChromiumControlCtrl::~CChromiumControlCtrl()
{
   m_MainDialog.DestroyWindow();
   CefShutdown();

   // TODO: Cleanup your control's instance data here.
}

The really simple client handler:
clienthandler.h
Code: Select all
#include "include/cef_client.h"

class ClientHandler : public CefClient, public CefLifeSpanHandler {

public:
   ClientHandler();

   CefRefPtr<CefBrowser> GetBrowser() { return m_Browser; }
   CefWindowHandle GetBrowserHwnd() { return m_BrowserHwnd; }

   // CefClient methods
   virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE{
      return this;
   }

   // Virtual on CefLifeSpanHandler
   virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
   virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
   virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;

protected:
   // The child browser window
   CefRefPtr<CefBrowser> m_Browser;

   // The child browser window handle
   CefWindowHandle m_BrowserHwnd;

   IMPLEMENT_REFCOUNTING(ClientHandler);
};

clienthandler.cpp
Code: Select all
//omit includes

ClientHandler::ClientHandler()
: m_Browser(NULL),
m_BrowserHwnd(NULL)
{

}

bool ClientHandler::DoClose(CefRefPtr<CefBrowser> browser)
{
   return false;
}

void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser)
{
   if (!m_Browser.get())   {
      // We need to keep the main child window, but not popup windows
      m_Browser = browser;
      //m_BrowserHwnd = browser->GetWindowHandle();
   }
}

void ClientHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{
   //if (m_BrowserHwnd == browser->GetWindowHandle()) {
   //    // Free the browser pointer so that the browser can be destroyed
   //    m_Browser = NULL;
   //}

   m_Browser = NULL;
}


Hope that this information help to find a solution or workaround for this problem and help other users that want develop ActiveX wrapper too.
Thanks.
ecreality
Newbie
 
Posts: 1
Joined: Wed Nov 05, 2014 10:18 am

Return to Support Forum

Who is online

Users browsing this forum: No registered users and 74 guests