unit uCheckPrevious;

interface
uses Windows, SysUtils;

function CheckIfRunning(const AExeName : String): Boolean;

function RestoreIfRunning(
                const AppHandle : THandle; 
                MaxInstances : integer = 1) : boolean;

implementation

uses
  TLHelp32, StrUtils, Forms;

type
  PInstanceInfo = ^TInstanceInfo;
  TInstanceInfo = packed record
    PreviousHandle : THandle;
    RunCounter : integer;
  end;

var
  MappingHandle: THandle;
  InstanceInfo: PInstanceInfo;
  MappingName : string;

  RemoveMe : boolean = True;

function CheckIfRunning(const AExeName : String): Boolean;
var
  MyHandle: THandle;
  hWnd : Cardinal;
  Struct: TProcessEntry32;
  ACadena : String;
  ACadena2 : String;
begin
  Result := False;
  ACadena2 := ExtractFileName(AExeName);
  try
    MyHandle := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);
    try
      Struct.dwSize:=Sizeof(TProcessEntry32);
      if Process32First(MyHandle, Struct) then
      begin
        ACadena := Struct.szExeFile;
        if Pos(ACadena2, ACadena) <> 0 then
        begin
          hWND := GetCurrentProcessId;
          if hWND <> Struct.th32ProcessID then
          begin
            Result := True;
            Exit;
          end;
        end;
      end;

      while Process32Next(MyHandle, Struct) do
      begin
        ACadena := Struct.szExeFile;
        if Pos(ACadena2, ACadena) <> 0 then
        begin
          hWND := GetCurrentProcessId;
          if hWND <> Struct.th32ProcessID then
          begin
            Result := True;
            Exit;
          end;
        end;
      end;
    finally
      CloseHandle(MyHandle);
    end;
  except on exception do
    //
  end
end;



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 CheckPrevious*)

