MVP Logo

Материализуя идеи

Не поднимешься в горы — не узнаешь высоты неба; не спустишься в бездну — не узнаешь толщи земли.

Recently, I got to, as many many years ago, dive in Windows API, to implement a rather simple task. I needed to restrict an FMX-based application, namely its Windows-flavour target, to be single-instance, so any attempt to launch yet anther copy of its process would (try to) bring up the first running one.

First, I got to say, that this solution is immature, kind of quick drop-in, and later it may grow into something more universal, regarding MAX OS platform as well. That's said, let's create two helper classes right in main project file code.

'At do we 'ave 'ere? :)

First, EsSingleInstanceGuard is a singleton, which should be created once an execution is reached main FMX entry point. Internally, it creates|opens an existing Named OS Mutexes. Named OS Windows Mutex is very useful here, because it exists at OS scope, not local to process, so different processes may request access to the same named mutex object.

Wht two named mutexes? Because one exists as User-local namespace, and another one, with Global prefix, apparently, at a global scope, which is shared among all User sessions.

Mutexes base name may naturally be a generated GUID string. In code snippet below, I use one GUID for x86 process, and another for 64 bit one.

In addition, Guard's class constructor registers the named Windows window message, and stores its ID in m_guardMsgId member. Wofur? That's the way we later notify the first instance to show itself on top of other windows. The good thing for named messages is that all processes which register it, will get the same message id. The guard's notifyInstance code does simply that, namely, sends a broadcast Windows window message, which is being dispatched to all process's main windows. The notifyInstance is performed only if guard detects it's a duplicate instance. After notification is sent, a duplicate immediately exits, before any other initializing actions are done.

The only step is left, is to allow our application to handle that broadcast message.

To allow our application to handle Guard broadcast message, whe got to implement so-called, Instance Subclassing for Application's internal HWND object. The second singleton helper class, EsSingleInstanceGuardMsgHook does exactly that.

It overrides, in a Windows way, the Application HWND's Windows Procedure, at the first step it checks and handles guard message, if detected, otherwise, it passes message handling to the "base class" procedure.

Yet one more positive side-effect of using named mutexes, is its application in Innosetup Installer Engine, which may use these mutex names to detect if application is running at the moment installer is launched, and prompt user to close an application, or exit installer.

Яндекс.Метрика

Сейчас 47 гостей и ни одного зарегистрированного пользователя на сайте

14.12.2019  ©2019 - ExactSoft - All rights reserved