http://delphi.about.com/library/weekly/aa100703a.htm
{ Article: Controling the number of application instances http://delphi.about.com/library/weekly/aa100703a.htm In this article you'll learn how to "run-once enable" a Delphi application that can check for its previous (running) instance. Along the process, several techniques of implementing such a check will be discussed; as well as how to bring your already running application to the foreground, if a user tries to run it "one more time". By the end of the article you'll have a copy-to-go code to control the behavior of your application's multiple instances: with the option to limit the number of running instances. } unit uCheckPrevious; interface uses Windows, SysUtils; function RestoreIfRunning( const AppHandle : THandle; MaxInstances : integer = 1 ) : boolean; implementation type PInstanceInfo = ^TInstanceInfo; TInstanceInfo = packed record PreviousHandle : THandle; RunCounter : integer; end; var MappingHandle : THandle; InstanceInfo : PInstanceInfo; MappingName : string; RemoveMe : boolean = True; function RestoreIfRunning( const AppHandle : THandle; MaxInstances : integer = 1 ) : boolean; begin Result := True; MappingName := StringReplace( ParamStr( 0 ), '\', '', [ rfReplaceAll, rfIgnoreCase ] ); MappingHandle := CreateFileMapping( $FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf( TInstanceInfo ), PChar( MappingName ) ); if MappingHandle = 0 then RaiseLastOSError else begin if GetLastError <> ERROR_ALREADY_EXISTS then begin InstanceInfo := MapViewOfFile( MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf( TInstanceInfo ) ); InstanceInfo^.PreviousHandle := AppHandle; InstanceInfo^.RunCounter := 1; Result := False; end else // already runing begin MappingHandle := OpenFileMapping( FILE_MAP_ALL_ACCESS, False, PChar( MappingName ) ); if MappingHandle <> 0 then begin InstanceInfo := MapViewOfFile( MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf( TInstanceInfo ) ); if InstanceInfo^.RunCounter >= MaxInstances then begin RemoveMe := False; if IsIconic( InstanceInfo^.PreviousHandle ) then ShowWindow( InstanceInfo^.PreviousHandle, SW_RESTORE ); SetForegroundWindow( InstanceInfo^.PreviousHandle ); end else begin InstanceInfo^.PreviousHandle := AppHandle; InstanceInfo^.RunCounter := 1 + InstanceInfo^.RunCounter; Result := False; end end; end; end; end; (* RestoreIfRunning *) initialization // nothing special here // we need this section because we have the // finalization section finalization // remove this instance if RemoveMe then begin MappingHandle := OpenFileMapping( FILE_MAP_ALL_ACCESS, False, PChar( MappingName ) ); if MappingHandle <> 0 then begin InstanceInfo := MapViewOfFile( MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf( TInstanceInfo ) ); InstanceInfo^.RunCounter := -1 + InstanceInfo^.RunCounter; end else RaiseLastOSError; end; if Assigned( InstanceInfo ) then UnmapViewOfFile( InstanceInfo ); if MappingHandle <> 0 then CloseHandle( MappingHandle ); end. (* unit uCheckPrevious *)
program XXX; uses Forms, ... uCheckPrevious in 'uCheckPrevious.pas'; {$R *.RES} begin if not uCheckPrevious.RestoreIfRunning( Application.Handle ) then begin Application.Initialize; Application.Title := 'Hex Editor'; Application.CreateForm( TMain, Main ); Application.Run; end; end.