Skip to main content
Thoughts from David Cornelius

Category

Having worked in Delphi for many years, I've seen the development tool and it's RTL evolve significantly, yet remain resilient in backwards compatibility. Early on, to prevent your application from running multiple times, there were generally two different approaches:

  1. Search for the name of your app's main form by name, or
  2. Search for a "mutex" created by your app.

 

There are other ways, but these two are the most popular I've seen. They both still work. The first one requires your application to actually show the main form--which obviously doesn't work for console applications. I'm writing an application that can be scheduled to run unattended and in that case will not be showing the main form, so I am using the second method. The last time I used this technique, I called CreateMutex which has a wrapper function in Delphi's RTL (see this forum for an example).

While reading about the threading and synchronizing topics in Delphi I found the TMutex class introduced way back in Delphi XE. I decided to put it to use, if for no other reason than for educational purposes. It turns out I like it better as it's more object-oriented.

I won't go into much detail as this is a fairly old topic with several examples and Windows API documentation that is still valid. So here's a code example:

program MutexExample;
uses
  Vcl.Forms, Vcl.Dialogs,
  System.SyncObjs, // defines TMutex
  Winapi.Windows,  // defines ERROR_SUCCESS
  Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
var
  AppMutex: TMutex = nil;
  MutexErr: Integer = 0;
procedure CheckSecondInstance;
const
  // any unique name will work--I chose to create a GUID
  UNIQUE_MUTEX_NAME = '{AD12094E-7308-4067-8CAC-565A1FF3ADDC}';
begin
  // try to create a mutex; don't need any security rights
  AppMutex := TMutex.Create(nil, True, UNIQUE_MUTEX_NAME);
  // check to see if it was successful
  MutexErr := GetLastError;
  // if not, previous instance of application already created the mutex
  if MutexErr <> ERROR_SUCCESS then
    ShowMessage(Application.Title + ' is already running.');
end;
begin
  // initialize app like normal, but don't start it yet
  Application.Initialize;
  Application.Title := 'Simple Mutex Example';

  // run our check here
  CheckSecondInstance;
  try
    // if the mutex was successfully created, this is the first instance of this app
    if MutexErr = ERROR_SUCCESS then begin
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end;
  finally
    // if a mutex was successfully created (and our app ran),
    // be sure to free it to release the mutex
    if Assigned(AppMutex) then
      AppMutex.Free;
  end;
end.

emozgun (not verified) Wed, 05/27/2020 - 12:42

Thanks David for unique Multiple Instances code running in FMX.
Just changed to work under Delphi 10:
"Vcl.Forms, Vcl.Dialogs," with "FMX.Dialogs,"
and
"finally if Assigned(AppMutex) then AppMutex.Free; end; end." with "except end; if Assigned(AppMutex) then AppMutex.Free; end."