Author: Embarcadero USA
Question and Answer Database FAQ1355D.txt Preventing multiple application instances Category :Windows API Platform :All Product :All 32 bit Question: How can I guarantee that only one instance of my program executes? Is it possible to restore the previous instance and shut down if I start more than one instance? Answer: Under Win16, you can check the value of hPrevInst at startup. If it is non-zero, then another instance of your application is running, and you can take steps to abort the current instance. Under Win32, hPrevInst is always zero and cannot be relied upon. You should attempt to create a uniquely named mutex. If the creation fails, then there is another instance running. The following example attempts to create a named mutex. If the mutex fails, a unique system wide custom windows message is registered with the system, and is then broadcast to all top level windows. The second instance then shuts down. The previous instance has also registered this unique custom system wide message, and has trapped the window procedure of Form1 to respond to this message. If the message is received, then Form1 is restored (if minimized) and then made to be the top level window. Care is taken in the example to minimize the effect of Delphi/Borland C++ Builder's hidden application window, and its effect on the task bar icon for Form1. Example: {The code for OneInstance.dpr} program OneInstance; uses Windows, Forms, Unit1 in 'Unit1.pas' {Form1}; {$R *.RES} begin {Attempt to create a named mutex} CreateMutex(nil, false, 'MyApp'); {if it failed then there is another instance} if GetLastError = ERROR_ALREADY_EXISTS then begin {Send all windows our custom message - only our other} {instance will recognise it, and restore itself} SendMessage(HWND_BROADCAST, RegisterWindowMessage('MyApp'), 0, 0); {Lets quit} Halt(0); end; Application.Initialize; {Tell Delphi to un-hide it's hidden application window} {This allows our instance to have a icon on the task bar} Application.ShowMainForm := true; ShowWindow(Application.Handle, SW_RESTORE); Application.CreateForm(TForm1, Form1); Application.Run; end. {The code for unit1.pas} unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} var OldWindowProc : Pointer; {Variable for the old windows proc} MyMsg : DWord; {custom systemwide message} function NewWindowProc(WindowHandle : hWnd; TheMessage : LongInt; ParamW : LongInt; ParamL : LongInt) : LongInt stdcall; begin if TheMessage = MyMsg then begin {Tell the application to restore, let it restore the form} SendMessage(Application.handle, WM_SYSCOMMAND, SC_RESTORE, 0); SetForegroundWindow(Application.Handle); {We handled the message - we are done} Result := 0; exit; end; {Call the original winproc} Result := CallWindowProc(OldWindowProc, WindowHandle, TheMessage, ParamW, ParamL); end; procedure TForm1.FormCreate(Sender: TObject); begin {Register a custom windows message} MyMsg := RegisterWindowMessage('MyApp'); {Set form1's windows proc to ours and remember the old window proc} OldWindowProc := Pointer(SetWindowLong(Form1.Handle, GWL_WNDPROC, LongInt(@NewWindowProc))); end; procedure TForm1.FormDestroy(Sender: TObject); begin {Set form1's window proc back to it's original procedure} SetWindowLong(Form1.Handle, GWL_WNDPROC, LongInt(OldWindowProc)); end; begin {Tell Delphi to hide it's hidden application window for now to avoid} {a "flash" on the taskbar if we halt due to another instance} ShowWindow(Application.Handle, SW_HIDE); end. 7/16/98 4:31:28 PM
Article originally contributed by