{
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.
}
Download zipped source
Project1.dpr
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
CheckPrevious in 'CheckPrevious.pas';
{$R *.res}
begin
//only two instances alowed
if not CheckPrevious.RestoreIfRunning(Application.Handle, 2) then
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end;
end.
CheckPrevious.pas
unit CheckPrevious;
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 CheckPrevious*)
{
********************************************
Zarko Gajic
About.com Guide to Delphi Programming
http://delphi.about.com
email: delphi.guide@about.com
free newsletter: http://delphi.about.com/library/blnewsletter.htm
forum: http://forums.about.com/ab-delphi/start/
********************************************
}