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

 zhou 发布于 2022-12-07 12:17

我知道我以前做过这件事,但似乎无法记住.

我有一个程序,我已经设置为使用可执行文件名上的互斥锁运行单例.单位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.

Dalija Prasn.. 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文档

1 个回答
  • 你使用错误的方法.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文档

    2022-12-11 03:12 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有