Disclosure Statement: This site contains affiliate links, which means that I may receive a commission if you make a purchase using these links. As an eBay Partner, I earn from qualifying purchases.

CEF4Delphi and CreateMutex in .dpr file

Post Reply
Christoph
Posts: 25
Joined: Fri Feb 23, 2018 6:31 am

CEF4Delphi and CreateMutex in .dpr file

Post by Christoph »

Hello,

trying to migrate a Delphi project (Delphi Tokyo 10.2) from CEF3 to CEF4Delphi was not successful, because we only run one instance of the application and we do avoid a second instance using CreateMutex. Using CEF4Delphi we run into the problem "Application already running"

A simple project to demonstrate the issue:

dpr:

program CEFTest;

uses
Vcl.Forms,
Vcl.Dialogs,
Winapi.Windows,
uCEFApplication,
UCEF1 in 'UCEF1.pas' {Form1};

{$R *.res}

var
mHandle : THandle;
MutexErr: Integer = 0;
Window: HWND;
begin
GlobalCEFApp := TCefApplication.Create;
GlobalCEFApp.SingleProcess := False;
GlobalCEFApp.Cache := 'cache';
GlobalCEFApp.Locale := 'de';

// try to create a mutex
mHandle := CreateMutex(nil, True, SWindowClassName);
// check to see if it was successful
MutexErr := GetLastError;

if MutexErr <> ERROR_SUCCESS then
begin
ShowMessage(SWindowClassName + ' already running!');
mHandle := FindWindow('TApplication',SWindowClassName);
ShowWindow(mHandle, SW_RESTORE);
SetForegroundWindow(Window);
end
else
begin
Application.Initialize;
if GlobalCEFApp.StartMainProcess then
begin
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end;
end;

GlobalCEFApp.Free;
end.

MainForm:

unit UCEF1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, uCEFChromium, Vcl.ExtCtrls,
uCEFWindowParent, uCEFChromiumWindow, uCEFRequest, uCEFPostData, uCEFPostDataElement,
uCEFMiscFunctions, uCEFInterfaces, uCEFConstants, uCEFTypes;

type
TForm1 = class(TForm)
Panel1: TPanel;
ChromiumWindow1: TChromiumWindow;
crm: TChromium;
Button1: TButton;
Timer1: TTimer;
procedure FormShow(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure crmAfterCreated(Sender: TObject; const browser: ICefBrowser);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;

var
Form1: TForm1;

const
SWindowClassName = 'CEF4App';

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
crm.LoadURL('www.google.de');
end;

procedure TForm1.crmAfterCreated(Sender: TObject; const browser: ICefBrowser);
begin
PostMessage(Handle, CEF_AFTERCREATED, 0, 0);
end;

procedure TForm1.FormShow(Sender: TObject);
begin
if not(crm.CreateBrowser(ChromiumWindow1, '')) then
Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
if not (crm.CreateBrowser(ChromiumWindow1, '')) and not (crm.Initialized) then
Timer1.Enabled := True;
end;

end.


Now just starting the programm results in the message, that the application is already running, without trying to load a URL

An idea how to solve this problem?

Best regards,
Christoph
User avatar
salvadordf
Posts: 4057
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: CEF4Delphi and CreateMutex in .dpr file

Post by salvadordf »

Use a different EXE for the subprocesses.

Take a look at the SubProcess or JSWindowBindingSubProcess demos to know how.
Christoph
Posts: 25
Joined: Fri Feb 23, 2018 6:31 am

Re: CEF4Delphi and CreateMutex in .dpr file

Post by Christoph »

Hello,

thank you very much, it is now working on our side!!

Best regards,
Christoph
User avatar
salvadordf
Posts: 4057
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: CEF4Delphi and CreateMutex in .dpr file

Post by salvadordf »

Please, use the SingleProcess mode only for debugging purposes.

The single process mode is not supported by CEF3 and it's a known cause for errors and access violations.
rgdawson
Posts: 22
Joined: Tue Apr 10, 2018 11:05 pm

Re: CEF4Delphi and CreateMutex in .dpr file

Post by rgdawson »

I also have a CEF4Delphi App and I want only a single instance to execute. I think you are need to call GlobalCEFApp.Free and Exit when you already have the app running and you do not want to run a second instance. This works. Here is what I have in the DPR file:

...

if GlobalCEFApp.StartMainProcess then
begin
{Allow Only Once Instance...}
if CreateMutex(nil, True, 'MUTEX-NAME') = 0 then
RaiseLastOSError;
if GetLastError = ERROR_ALREADY_EXISTS then
begin
MessageDlg('My App'#13#10#13#10'MyApp is already running. Only one instance can run per session.', mtInformation, [mbOK], 0);
GlobalCEFApp.Free;
Exit;
end;

Application.Initialize;
Application.ShowMainForm := False;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TMainForm, MainForm);
Application.CreateForm(TLogWindowForm, LogWindowForm);
Application.CreateForm(TDM, DM);
Application.CreateForm(TSplitViewForm, SplitViewForm);
Application.Run;
end;

GlobalCEFApp.Free;

end.
Post Reply