Preventing Multiple Application Instances in Delphi with TMutex

Categories: Programming, Windows
Comments: No Comments
Published on: October 20, 2015

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

*



Welcome , today is Sunday, October 22, 2017