Archive for the ‘Windows API’ Category

Delphi – Single application instance

Limiting an application to start just once per machine is usually required when an external resource such as a Comport is accessed. This feature is achieved by allocation of a global variable, such as a mutex.

FINDWINDOW METHOD:

The easiest way to look for an already running instance of an application is to use the FindWindow API function. The FindWindow function retrieves the handle of the window provided with the class name and window caption. In Delphi, the name of the window (form) class is the name of the form’s class, for example ‘TForm1’. Here’s the code:

 

program Project1;

uses
  Forms, Windows,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}
var
  PreviousHandle : THandle;
begin
  PreviousHandle := FindWindow('TForm1','Form1');
  if PreviousHandle = 0 then
  begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
  end
  else
    SetForegroundWindow(PreviousHandle);
end.

 

In our sample application we have only one form: Form1. This form is the main form of the project. To find a copy of the application already running, we can call the FindWindow API function that retrieves the handle of an existing window (the main form of the application). If the function fails (window with a specified class name and caption canot be found) the function returns 0. If the function returns the non-zero handle value, meaning that the system has found a window with specified parameters, we use the SetForegroundWindow API call. This function, provided with the window handle, activates the window and brings it to the foreground – making it the active window. Since Form1 is the main window of the application – the (already running) application becomes active. However, if the window was minimized we’ll first need to restore it to its previous state and then bring it to “top”.

The code above might look ok, but is not what we want.
First, such a code would prevent you from running your application from the IDE (at design time) – since at design time the window with the specified class name and the caption already exists, it’s the design time window of your main form.
Second, this code is not so safe, since there may be many Delphi applications on the system running, that have a form whose class name is “TForm1” – how can you be sure that this particular form (window) found by the FindWindow function is in fact a form belonging to your application? You cannot.

To overcome this problem, we’ll turn to threading. In Windows, one common way of object synhronization is creating a mutex object (mutually exclusive). In general, mutexes are used to synchronize two (or more) different applications – in our case we’ll create a mutex to synchronize instances of the same application. 

 

Mutex – could do
The following code attempts to create a named mutex. If the function (CreateMutex) fails, you can be sure that an instance of the application is already running.

program Project1;

uses
  Forms, Windows,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}
var
  Mutex : THandle;
begin
  Mutex := CreateMutex(nil, True, 'My_Unique_Application_Mutex_Name');
  if (Mutex = 0) OR (GetLastError = ERROR_ALREADY_EXISTS) then
  begin

    // code to searh for, and activate
    // the previous (first) instance

  end
  else
  begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
    if Mutex <> 0 then
      CloseHandle(Mutex);
    end;
  end;
end.
.
 Continue reading