防止程序重复执行 Controling the number of application instances

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.

原文地址:https://www.cnblogs.com/shangdawei/p/3060435.html