Mega Code Archive

 
Categories / Delphi / Examples
 

Preventing multiple application instances (final answer ;) )

Title: Preventing multiple application instances (final answer ;) ) Question: How to prevent second lunch of Your application and activate the previous instance instead Answer: Yes, I know about all articles about the same qustion ;) But I hadn't seen this method description. My decision gives You ability either prevent previous instance lunching and (optional) activating previous instance instead. It's based on memory mapped files and works fine in Win9x/NT/2000. simply place in .dpr file this lines (after 'begin') if CheckAppAlreadyRunning ('MyApplicationSign') then EXIT; (here 'MyApplicationSign' - unique ID for this application) and inlude in Your project unit with following function: {$IFDEF VER120} { Delphi 4.0} {$DEFINE D4_} {$ENDIF} {$IFDEF VER130} { Delphi 5.0} {$DEFINE D4_} {$ENDIF} const CheckAppRunningMFile : THandle = 0; function CheckAppAlreadyRunning (const AppSign : string; BringToFront : boolean {$IFDEF D4_}= true{$ENDIF}; DestroyOnExit : boolean {$IFDEF D4_}= false{$ENDIF}) : boolean; // prevent double-starting of application. AppSign // - unique identifier of application (this function // will make MMF with this name) // If BringToFront then send to prev instance msg RESTORE. // If DestroyOnExit, then mapview will be closed (only for presence check, // will not prevent starting apps with this AppSign). var p : Pointer; AppWnd, TopWnd: HWND; begin Result := false; if Result then ; // Kill compiler's stupid hint !!! CheckAppRunningMFile := CreateFileMapping ( THandle ($FFFFFFFF), // use paging file nil, // no security attributes PAGE_READWRITE, // read/write access 0, // size: high 32 bits 4096, // size: low 32 bits PChar(AppSign) // name of map object ); if CheckAppRunningMFile = 0 then raise Exception.Create ( 'CheckAppAlreadyRunning: can''t create file mapping'); try { close CheckAppRunningMFile if DestroyOnExit} Result := GetLastError() = ERROR_ALREADY_EXISTS; p := MapViewOfFile ( CheckAppRunningMFile, // object to map view of FILE_MAP_WRITE, // read/write access 0, // high offset: map from 0, // low offset: beginning 0 // default: map entire file ); if p = nil then raise Exception.Create ( 'CheckAppAlreadyRunning: can''t create map view of file.'); try { p must die} if Result then begin // already running if BringToFront then begin Move (p^, AppWnd, SizeOf (AppWnd)); if AppWnd 0 then begin if IsIconic (AppWnd) then SendMessage (AppWnd, WM_SYSCOMMAND, SC_RESTORE, 0); TopWnd := GetLastActivePopup (AppWnd); if (TopWnd 0) and (TopWnd AppWnd) and IsWindowVisible (TopWnd) and IsWindowEnabled (TopWnd) then SetForegroundWindow (TopWnd); end; end; end else begin // first instance AppWnd := Application.Handle; Move (AppWnd, p^, SizeOf (AppWnd)); end; finally UnmapViewOfFile (p); end; { of try p must die} finally if DestroyOnExit and (CheckAppRunningMFile 0) then begin CloseHandle (CheckAppRunningMFile); CheckAppRunningMFile := 0; end end; { of try 'close CheckAppRunningMFile if DestroyOnExit'} end; { of function CheckAppAlreadyRunning --------------------------------------------------------------} initialization finalization if CheckAppRunningMFile 0 then CloseHandle (CheckAppRunningMFile);