doublecmd/src/uuniqueinstance.pas
2010-02-09 08:43:01 +00:00

190 lines
4.2 KiB
ObjectPascal

unit uUniqueInstance;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, SimpleIPC;
type
TOnUniqueInstanceMessage = procedure (Sender: TObject; Params: array of UTF8String; ParamCount: Integer) of object;
{ TUniqueInstance }
TUniqueInstance = class
private
FInstanceName: UTF8String;
FServerIPC: TSimpleIPCServer;
FClientIPC: TSimpleIPCClient;
FOnMessage: TOnUniqueInstanceMessage;
procedure OnNative(Sender: TObject);
procedure CreateServer;
procedure CreateClient;
public
constructor Create(aInstanceName: String);
destructor Destroy; override;
function IsRunInstance: Boolean;
procedure SendParams;
procedure SendString(aStr: UTF8String);
procedure RunListen;
procedure StopListen;
property OnMessage: TOnUniqueInstanceMessage read FOnMessage write FOnMessage;
end;
function IsUniqueInstance(aInstanceName: String): Boolean;
{en
Returns @true if current application instance is allowed to run.
Returns @false if current instance should not be run.
}
function IsInstanceAllowed: Boolean;
var
UniqueInstance: TUniqueInstance = nil;
implementation
uses
StrUtils, FileUtil, uGlobs;
const
Separator = '|';
{ TUniqueInstance }
procedure TUniqueInstance.OnNative(Sender: TObject);
var
sTemp: UTF8String;
sTempArray: array of UTF8String;
mtMsgCount: TMessageType;
I: Integer;
begin
if Assigned(FOnMessage) then
begin
mtMsgCount:= FServerIPC.MsgType;
sTemp:= FServerIPC.StringMessage;
SetLength(sTempArray, mtMsgCount);
for I:= 0 to mtMsgCount - 1 do
sTempArray[I] := Copy2SymbDel(sTemp, Separator);
FOnMessage(Self, sTempArray, mtMsgCount);
SetLength(sTempArray, 0);
end;
end;
procedure TUniqueInstance.CreateServer;
begin
if FServerIPC = nil then
begin
FServerIPC:= TSimpleIPCServer.Create(nil);
FServerIPC.OnMessage:= @OnNative;
end;
if FClientIPC <> nil then
FreeAndNil(FClientIPC);
end;
procedure TUniqueInstance.CreateClient;
begin
if FClientIPC = nil then
FClientIPC:= TSimpleIPCClient.Create(nil);
end;
function TUniqueInstance.IsRunInstance: Boolean;
begin
CreateClient;
FClientIPC.ServerID:= FInstanceName;
Result:= FClientIPC.ServerRunning;
end;
procedure TUniqueInstance.SendParams;
var
sTemp: UTF8String;
I: Integer;
begin
CreateClient;
FClientIPC.ServerID:= FInstanceName;
if not FClientIPC.ServerRunning then Exit;
sTemp:= EmptyStr;
for I:= 1 to ParamCount do
sTemp:= sTemp + Separator + SysToUTF8(ParamStr(I));
try
FClientIPC.Connect;
FClientIPC.SendStringMessage(ParamCount, sTemp);
finally
FClientIPC.Disconnect;
end;
end;
procedure TUniqueInstance.SendString(aStr: UTF8String);
begin
CreateClient;
FClientIPC.ServerID:= FInstanceName;
if not FClientIPC.ServerRunning then Exit;
try
FClientIPC.Connect;
FClientIPC.SendStringMessage(mtString, aStr + Separator);
finally
FClientIPC.Disconnect;
end;
end;
procedure TUniqueInstance.RunListen;
begin
CreateServer;
FServerIPC.ServerID:= FInstanceName;
FServerIPC.Global:= True;
FServerIPC.StartServer;
end;
procedure TUniqueInstance.StopListen;
begin
if FServerIPC = nil then Exit;
FServerIPC.StopServer;
end;
constructor TUniqueInstance.Create(aInstanceName: String);
begin
FInstanceName:= aInstanceName;
end;
destructor TUniqueInstance.Destroy;
begin
if Assigned(FClientIPC) then
FreeAndNil(FClientIPC);
if Assigned(FServerIPC) then
FreeAndNil(FServerIPC);
inherited Destroy;
end;
function IsUniqueInstance(aInstanceName: String): Boolean;
begin
Result:= True;
UniqueInstance:= TUniqueInstance.Create(aInstanceName);
if UniqueInstance.IsRunInstance then
begin
UniqueInstance.SendString('ShowMainForm');
Exit(False);
end;
UniqueInstance.RunListen;
end;
function IsInstanceAllowed: Boolean;
begin
Result := (not gOnlyOneAppInstance) or IsUniqueInstance(ApplicationName);
end;
finalization
if Assigned(UniqueInstance) then
begin
UniqueInstance.StopListen;
FreeAndNil(UniqueInstance);
end;
end.