CEF4Delphi and CreateMutex in .dpr file
Posted: Fri Feb 23, 2018 7:11 am
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
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