{ 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;interfaceuses Windows, SysUtils;function RestoreIfRunning( const AppHandle : THandle; MaxInstances : integer = 1 ) : boolean;implementationtype 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 sectionfinalization// remove this instanceif RemoveMe thenbegin 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.