Delphi基于命令行参数限制程序的单个实例

时间:2014-12-08 17:58:44

标签: delphi singleton delphi-xe6

我知道我以前做过这件事,但似乎不记得如何。

我有一个程序,我已设置为使用可执行文件名上的互斥锁运行单例。 单位GlobalSU;

interface
 function IsAppRunning: Boolean;

implementation

uses
 Windows, SysUtils, Forms;

function IsAppRunning: Boolean;
var
 rtn : Cardinal;
begin
  result := False;
  CreateMutex(nil, False, PWideChar(ExtractFileName(Application.ExeName)));
  rtn := GetLastError;
  if rtn = ERROR_ALREADY_EXISTS then
   result := True;
end;

程序接受某些命令行参数,这些参数指示要处理的数据。我不希望使用相同的命令行参数运行多个程序实例。但我确实希望能够用不同的参数启动第二个实例。

我大约一年前做过这个,但不记得怎么做。我使用DPR中的命令行参数修改名称,然后使用互斥锁对其进行测试。

我尝试重命名Application.ExeName,但它是只读的,所以我一定是在改变别的东西。

以下代码不会编译,但会添加以澄清我想要做的事情。 顺便说一下 - ' ##"始终是第三个参数的前两个字符,但我用RegEx测试它。

program EPRmailer;

uses
  Vcl.Forms,
  uMainMailer in 'uMainMailer.pas' {frmMainMailer},
  configXML in 'configXML.pas',
  GlobalSU in 'GlobalSU.pas',
  CVUtils in 'CVUtils.pas',
  QMConst in 'QMConst.pas',
  ServerAttachmentDMu in 'ServerAttachmentDMu.pas';

{$R *.res}
 var
   i : integer;
begin

  for i := 0 to ParamCount do
  if TestParam('##', ParamStr(i)) then
  Application.ExeName := Application.ExeName + '-' + ParamStr(i);

  if IsAppRunning then exit;

  Application.Initialize;
  ReportMemoryLeaksOnShutdown := DebugHook <> 0;
  Application.MainFormOnTaskbar := false;
  Application.CreateForm(TfrmMainMailer, frmMainMailer);
  frmMainMailer.RunEPR;

end.

1 个答案:

答案 0 :(得分:8)

你使用的是错误的做法。您应该将可配置字符串发送到测试重复应用程序的函数,而不是重命名Application.ExeName

function CreateSingleInstance(const InstanceName: string): boolean;
var
  MutexHandle: THandle;
begin
  MutexHandle := CreateMutex(nil, false, PChar(InstanceName));
  // if MutexHandle created check if already exists
  if (MutexHandle <> 0) then
    begin
      if GetLastError = ERROR_ALREADY_EXISTS then
        begin
          Result := false;
          CloseHandle(MutexHandle);
        end
      else Result := true;
    end
  else Result := false;
end;

var
  MyInstanceName: string;
begin
  Application.Initialize;
  // Initialize MyInstanceName here
  ...
  if CreateSingleInstance(MyInstanceName) then
    begin
      // Form creation 
      ...
    end
  else Application.Terminate;
end. 

函数CreateSingleInstance应该在应用程序中使用一次,因为它会分配在应用程序终止之前保持活动状态的互斥锁,然后Windows将自动关闭互斥锁句柄。

注意:如果MyInstanceName超过MAX_PATH个字符或包含反斜杠'\'字符,则功能将失败

CreateMutex documentation