Solved

Is my application currently running?

Posted on 2004-04-17
11
860 Views
Last Modified: 2010-04-05
I am trying to ensure that only one instance of my Delphi 3 application is running in memory at any given time, on one computer.   I tried using the following code, but it is unreliable...

// The following code ensures that your .exe will only run once:
{Searches table to see if the program is already running}
if GlobalFindAtom('PROGRAM_RUNNING') = 0 then begin
      { If not found then add it }
      atom := GlobalAddAtom('PROGRAM_RUNNING')
end else begin
      { If program is already running the show message and halt }
      Halt;
end;

...where "atom" is defined as a global integer.

The problem is that if the program crashes, it is impossible to relaunch the application without triggering the "Halt" procedure.  Evidently the Atom is not cleared up when the application has a fatal exception that terminates the program.

Is there a more reliable method of ensuring that my application is only in memory once?

Thanks.
0
Comment
Question by:Monroe406
  • 5
  • 5
11 Comments
 
LVL 26

Assisted Solution

by:Russell Libby
Russell Libby earned 40 total points
ID: 10850272

Yes, use a named event or named mutex. These handles are tied to the process, and will be closed when the process dies. (unlike the atom table, where a GlobalDeleteAtom, or a reboot is required to clear the atom)

Regards,
Russell
0
 
LVL 9

Expert Comment

by:Cayce
ID: 10850309
0
 

Author Comment

by:Monroe406
ID: 10850371
>> unlike the atom table, where a GlobalDeleteAtom, or a reboot is required to clear the atom

Well, I forgot to add that on my main form's OnDestroy event I do have a GlobalDeleteAtom call...

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
      {Removes the item from the table so it can be run again}
      GlobalDeleteAtom(atom);
end;

It's simply not reliable.
0
 

Author Comment

by:Monroe406
ID: 10850383
>> use a named event or named mutex

I've tried the following using a Mutex, but is does not work.  I can launch dozens of instances of the same program with the following failed code...

public
        { Public declarations }
        Mutex: THandle;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
      Mutex := CreateMutex(nil, True,
            PChar(ExtractFileName(Application.ExeName)));
      if Mutex = 0 then
      begin
        Application.ShowMainForm := False;
        Application.Terminate; // See FormDestroy for house cleaning
      end;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
      if Mutex <> 0 then ReleaseMutex(Mutex);
end;
0
 
LVL 9

Expert Comment

by:Cayce
ID: 10850418
this is pseudocode, I don't have delphi on my current computer so I don't want to post buggy code:

 >> use a named event or named mutex

I've tried the following using a Mutex, but is does not work.  I can launch dozens of instances of the same program with the following failed code...

OnCreate Event()
begin
   Mutex := OpenMutex(mutexname);
   if Mutex = 0 then
     begin
       Mutex = CreateMutex(mutexname);
        if Mutex <> 0 then
          { continue executing app }
     end  
  else
    begin
      ReleaseMutex(Mutex);
      {terminate application}
    end;      
end;

OnDestroy Event()
begin
  if Mutex <> 0 then ReleaseMutex(Mutex);
end;

On the other things it's a better idea to do the mutex checking on the .dpr file.

Right there:

begin
 {check mutex here}
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:Monroe406
ID: 10850428

I think I found a solution...

If I add a few more conditionals, then the second instance of the application will be caught and terminated.  Instead of using just "if Mutex = 0 then..." I find that the following conditional statement works...

if ( GetLastError() = ERROR_ALREADY_EXISTS ) or
        ( WaitForSingleObject(Mutex,100) = WAIT_TIMEOUT ) or
        ( Mutex = 0 ) then begin
        Application.ShowMainForm := False;
        Application.Terminate; // See FormDestroy for house cleaning
end;
0
 
LVL 9

Expert Comment

by:Cayce
ID: 10850440
You should not wait for the Mutex, that will make your application wait (while loaded in memory) for the mutex to be released (wait forthe other instance(s) to be closed).
0
 
LVL 9

Expert Comment

by:Cayce
ID: 10850457
OH! I didn't see your were waiting just for 100 milliseconds. Anyway it's better to do the checking on the .dpr so the main form is never created and the ReleaseMutex always happens.
0
 
LVL 9

Accepted Solution

by:
Cayce earned 60 total points
ID: 10850475
Mutex: THandle;
begin
  try
    {create for mutex in here}
    if ( GetLastError() = ERROR_ALREADY_EXISTS ) or
      ( WaitForSingleObject(Mutex,100) = WAIT_TIMEOUT ) or
       ( Mutex = 0 ) then
         begin
                 Application.ShowMainForm := False;
          end
      else
          begin
             Application.Initialize;
             Application.CreateForm(TForm1, Form1);
             Application.Run;
          end;
  finally
    ReleaseMutex(Mutex);
  end;
end.
0
 

Author Comment

by:Monroe406
ID: 10851017
>> Mutex: THandle;


You cannot put the above line by itself in a DPR.  The source code will not compile...

There is something you've left out of your above example.
0
 

Author Comment

by:Monroe406
ID: 10851067
The following needs to be added to your example to work...

uses
      Sysutils,
      Windows,
..

var
      Mutex: THandle;

...
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now