我试图让我的应用程序只在计算机上运行一次,我的应用程序需要通信到web服务,所以让它运行不止一次是不好的,目前我正在使用Mutex:
MyMsg := RegisterWindowMessage('My_Unique_App_Message_Name'); Mutex := CreateMutex(nil,True,'My_Unique_Application_Mutex_Name'); if (Mutex = 0) OR (GetLastError = ERROR_ALREADY_EXISTS) then exit;
目前这可以限制每个用户的1个应用程序实例,但我的应用程序正在Windows服务器环境中使用,一次有20个用户,所以我需要严格要求每个服务器只运行一次,我是什么试图做的是将Mutex声明为全局互斥锁,但是当我执行下一个代码时它没有这样做它根本不起作用.
MyMsg := RegisterWindowMessage('My_Unique_App_Message_Name'); Mutex := CreateMutex(nil,'Global\My_Unique_Application_Mutex_Name'); if (Mutex = 0) OR (GetLastError = ERROR_ALREADY_EXISTS) then begin exit
我做错了什么?有没有其他可靠的方法不让我的应用程序的第二个实例运行?
解决方法
默认情况下,lpMutexAttributes = nil创建的互斥锁只能由运行该进程的用户访问.所有用户都需要访问互斥锁.
空DACL安全描述符
通过使用具有空DACL的安全描述符来执行此操作.请在下面找到我用于单实例应用程序/服务的代码
//Creates a mutex to see if the program is already running. function IsSingleInstance(MutexName : string; KeepMutex : boolean = true):boolean; const MUTEX_GLOBAL = 'Global\'; //Prefix to explicitly create the object in the global or session namespace. I.e. both client app (local user) and service (system account) var MutexHandel : THandle; SecurityDesc: TSecurityDescriptor; SecurityAttr: TSecurityAttributes; ErrCode : integer; begin // By default (lpMutexAttributes =nil) created mutexes are accessible only by // the user running the process. We need our mutexes to be accessible to all // users,so that the mutex detection can work across user sessions. // I.e. both the current user account and the System (Service) account. // To do this we use a security descriptor with a null DACL. InitializeSecurityDescriptor(@SecurityDesc,SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(@SecurityDesc,nil,False); SecurityAttr.nLength:=SizeOf(SecurityAttr); SecurityAttr.lpSecurityDescriptor:=@SecurityDesc; SecurityAttr.bInheritHandle:=False; // The mutex is created in the global name space which makes it possible to // access across user sessions. MutexHandel := CreateMutex(@SecurityAttr,PChar(MUTEX_GLOBAL + MutexName)); ErrCode := GetLastError; // If the function fails,the return value is 0 // If the mutex is a named mutex and the object existed before this function // call,the return value is a handle to the existing object,GetLastError // returns ERROR_ALREADY_EXISTS. if {(MutexHandel = 0) or }(ErrCode = ERROR_ALREADY_EXISTS) then begin result := false; closeHandle(MutexHandel); end else begin // Mutex object has not yet been created,meaning that no prevIoUs // instance has been created. result := true; if not KeepMutex then CloseHandle(MutexHandel); end; // The Mutexhandle is not closed because we want it to exist during the // lifetime of the application. The system closes the handle automatically //when the process terminates. end;