Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: How control application instance in win32 or win64 XE7?


This question is answered.


Permlink Replies: 6 - Last Post: Jun 15, 2016 5:45 PM Last Post By: Remy Lebeau (Te...
Maycoll Trevezani

Posts: 28
Registered: 1/20/11
How control application instance in win32 or win64 XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 25, 2015 6:49 AM
Hi guys,

I have a problem on control of my application instance.

I tryed:
  //project source 
 
  myHwnd := FindWindow('TApplication', 'MyApplicaton');
 
  if (myHwnd > 0) then
    exit;


But this way, finds always current execution of application.

How ensure that my application run only one time?
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: How control application instance in win32 or win64 XE7?
Correct
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 25, 2015 10:11 AM   in response to: Maycoll Trevezani in response to: Maycoll Trevezani
Maycoll wrote:

But this way, finds always current execution of application.

Are you sure? FireMonkey does not have a TApplicaton window like VCL does.

In any case, your current instance is the active instance and its HWND (if
it has one) would be higher up in the current z-order. For VCL at least,
the trick to making this work would be to clear the TApplication.Title before
calling FindWindow(), but that property has no effect in FireMonkey. The
alternative would be to call FindWindow/Ex() in a loop, or use EnumWindows(),
and ignore any HWND that belongs to the current process.

How ensure that my application run only one time?

FindWindow() is not the correct way to do that in the first place. The common
approach is to use a named mutex via CreateMutex() instead, eg:

myMutex = CreateMutex(NULL, FALSE, 'MyAppMutex');
if myMutex <> 0 then
begin
  if GetLastError = ERROR_ALREADY_EXISTS then
    Exit;
end else
begin
  if GetLastError = ERROR_ACCESS_DENIED then
    Exit;
  RaiseLastOSError;
end


--
Remy Lebeau (TeamB)
Maycoll Trevezani

Posts: 28
Registered: 1/20/11
Re: How control application instance in win32 or win64 XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 25, 2015 12:11 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Thanks a lot Remy

Following your sugestion, i had success with this code:

//project source
 
Type
  TdhsOneInstanceApp = Class(TObject)
    private
      FMutex     : THandle;
      FAppTitle  : Array[0..$100] of char;
      procedure CheckForAnotherInstance;
    public
      constructor Create;
  end;
 
var
   OneInstanceApp : TdhsOneInstanceApp;
 
constructor TdhsOneInstanceApp.Create;
begin
  strPCopy(FappTitle,Application.Title);
  CheckForAnotherInstance;
end;
 
procedure TdhsOneInstanceApp.CheckForAnotherInstance;
var
   hRunningApp : THandle;
begin
  // .. This mutex will be freed when the applcation closes!
  FMutex := CreateMutex (nil, FALSE, FAppTitle );
 
  if WaitForSingleObject(FMutex, 0) = wait_TimeOut then
  begin
     // Found another instance
     MyVarCheck := true;
  end;
end;
 
 
begin
  Application.Title := 'MyApp';
  OneInstanceApp := TdhsOneInstanceApp.Create;
 
  if MyVarCheck then
    exit
  else
  begin
    Application.Initialize;
    Application.CreateForm(TFrmMyForm, FrmMyForm);
    Application.Run;
  end;    
 
end;

I found in http://cc.embarcadero.com/item/15413

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: How control application instance in win32 or win64 XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 25, 2015 1:23 PM   in response to: Maycoll Trevezani in response to: Maycoll Trevezani
Maycoll wrote:

Following your sugestion, i had success with this code:

I would suggest using a String instead of a Char array for the FAppTitle
field, or just get rid of FAppTitle altogether and just use Application.Title
directly.

You are also not checking if CreateMutex() fails, or if it succeeds because
the mutex already existed. And there is no need to use WaitForSingleObject()
at all, as you do not need to care about the mutex's ownership, only its
existence.

And you are leaking your OneInstanceApp object. I would personally get rid
of the class and just use a function instead.

Try something more like this:


var
  OneInstanceMutex: THandle = 0;
 
function InstanceAlreadyExists(const MutexName: string): Boolean;
begin
  Result := False;
  // .. This mutex will be freed when the application closes!
  OneInstanceMutex := CreateMutex (nil, FALSE, PChar(MutexName) );
  if OneInstanceMutex <> 0 then
  begin
    if GetLastError() = ERROR_ALREADY_EXISTS then
    begin
      // Found another instance
      Result := True;
    end;
  end else
  begin
    if GetLastError() = ERROR_ACCESS_DENIED then
    begin
      // Found another instance
      Result := True;
    end;
  end;
end;
 
begin
  if InstanceAlreadyExists('MyApp') then
    Exit;
 
  Application.Initialize;
  Application.Title := 'MyApp';
  Application.CreateForm(TFrmMyForm, FrmMyForm);
  Application.Run;
end;


--
Remy Lebeau (TeamB)
Maycoll Trevezani

Posts: 28
Registered: 1/20/11
Re: How control application instance in win32 or win64 XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 25, 2015 2:03 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Great,

I realy needed only this code. Short and functional.

Thanks.
Mário Reis

Posts: 26
Registered: 9/16/06
Re: How control application instance in win32 or win64 XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 15, 2016 4:53 PM   in response to: Maycoll Trevezani in response to: Maycoll Trevezani
This code doesn't seam to work on MDI MainForm! I already tryed almost every and it doesn't display no message window at all.
I eve try
if InstanceAlreadyExists('GESTACRA_XE7') then
Begin
if (MainForm.Active) then
CreateStatusWindow('Já tem uma sessão em utilização!');
Else
ShowMessage('Já tem uma sessão em utilização!') ;
/

Exit;
End;
Any ideas?
Best regards
Mário Reis

Maycoll Trevezani wrote:
Great,

I realy needed only this code. Short and functional.

Thanks.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: How control application instance in win32 or win64 XE7?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 15, 2016 5:45 PM   in response to: Mário Reis in response to: Mário Reis
Mário wrote:

This code doesn't seam to work on MDI MainForm!

The code I showed earlier is not dependent on the MainForm's type.

Besides, the check for a previous instance should be performed before any
Form is created in the first place, like I showed in my earlier example.
Especially since InstanceAlreadyExists() creates the mutex if it does not
already exist yet, so you need to do that as early as possible so subsequent
instances can find it.

I do not understand what the actual problem is that you are having now.
Please clearify.

--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02