- Find process in process list
- Find window name
- Checking existence and status (locked or free) of a file
- Using OS flags
My favorite is using OS flags, since in my opinion it's the simplest from all the methods. And from several OS flags (or several features that can be used as a flag) provided by Windows, Mutex is my favorite one. You can read more details abut mutex here.
Mutex: The Basics
Quoted from msdn article:
You can use a mutex object to protect a shared resource from simultaneous access by multiple threads or processes. Each thread must wait for ownership of the mutex before it can execute the code that accesses the shared resource. For example, if several threads share access to a database, the threads can use a mutex object to permit only one thread at a time to write to the database.
From the excerpt above we can deduce that an application can create mutex that unique and detectable from other applications. Therefore we should detect our mutex before move onto the main code of a program. If the mutex exists we should terminate the current process, otherwise we create the mutex ourselves and continue to main code.
The creator of the mutex (i.e. the first instance) must destroy or release the mutex when it is terminated. This is to make sure that the mutex does not exist anymore, so the next first instance of our program can create the mutex successfully. However it's just a good practice. Because Windows actually keeps records of mutex owner. Once the owner got terminated, the mutex will also be destroyed.
Our pseudocode is:
begin if MutexIsExists(OurMutexID) then Terminate else begin CreateMutex(OurMutexID); Goto MainProgram; DestroyMutex; end; end;
Code Implementation
For this tutorial in dealing with mutex we'll be relying on windows api CreateMutex. Official details of CreateMutex is available here.
To check the existence of a mutex we have to call CreateMutex to create a mutex with a specific name, and set us (the caller) as the owner of the mutex. If mutex with the same name already exists, CreateMutex can not set us as the owner and it will raise error with code ERROR_ALREADY_EXISTS (183). If it does not exist, then CreateMutex will succesfully create the mutex and return the handle of the mutex.
In Delphi project, the best place to put the checking code is in .dpr file, immediately after enter the main begin...end block. But this is not mandatory, you can put the checking code in any other place that you want according to specific requirements.
Here is the sample code, in this tutorial we want to show a message before terminating if the same program is already running.
program SingleInstance; uses Windows, Forms, Dialogs, Main_SingleInstance in 'Main_SingleInstance.pas' {Form1}; {$R *.res} const MutexName = 'CodeCall.Net Mutex'; resourcestring DUPLICATE_MSG = 'Another instance of this program is already running. This one will shutdown'; var vMutex: THandle; begin // try to create our mutex vMutex := CreateMutex(nil, True, MutexName); // check if the previous line caused error and the error is ERROR_ALREADY_EXISTS if GetLastError = ERROR_ALREADY_EXISTS then begin // show the duplication message MessageDlg(DUPLICATE_MSG, mtError, [mbOk], 0); Exit; // terminates the program end; try Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; finally // release the mutex CloseHandle(vMutex); end; end.
After compilation, let's try the demo program. First execute will nicely show our main form like this:
[ATTACH]3670[/ATTACH]
Now while the first one is still running, try to execute the same exe once again. This time it will show an error message like shown below. After we close the message, it will immediately terminate.
[ATTACH]3669[/ATTACH]
Full source code of the demo project is attached. Feel free to use or improve.
Attached Files
Edited by LuthfiHakim, 20 March 2011 - 04:17 PM.
fixing code formatting and tag error