Single Instance Application - The simple solution






1.75/5 (6 votes)
Nov 22, 2002
3 min read

100394

1579
The solution for the single instance application issue with command line arguments.
Introduction
Here is one more solution to solve the one instance application issue. The main distinguishing feature of this implementation is simplicity. It's not bound to MFC and can be used in pure Win32 application, no matter GUI or console. But MFC version is also present. There are two demo projects (MFC and Win32) to demonstrate how it works. Try to start several instances to see what happens.
How does this work
The first instance of application creates file mapping, registers window message and save its thread ID in the file mapping. The second instance opens the file mapping, copies its command line to the file mapping and posts registered window message to the first instance thread. The posted message notifies the first instance that command line of the second instance is available. So, it uses one file mapping and one registered windows message. Implementation is very lightweight - you don't have to pay much for such a common task.
Background
I wrote this in response to Single Instance Application by Justin Hallet . I found his implementation too complicated (one mutex, one thread, one file mapping, two events - whoa, this is overhead!). Indeed, because such a code keeps the computer running needlessly, it also needlessly increases the entropy of the universe, thereby hastening said heat death. In short, such a code is quite environmentally unfriendly and should be considered a threat to our species :). (Copyright © 2002 Herb Sutter )
Implementation presented here is made as simple as possible.
Using the code with MFC
It's very simple to use it with MFC.
- Derive your application class from
CSingleInstanceApp
instead ofCWinApp
. Do not forget to include SingleInstanceApp.h in your application class header. -
Replace all references to
CWinApp
withCSingleInstanceApp
in yourCSingleInstanceApp
-derived class. -
Add the code to the
CMyApp
constructor: - Add the check to
InitInstance
method of your application class. -
Optional. Override the
CSingleInstanceApp::OnSecondInstance
method to get notified when the second instance is being tried to start. You can use here theCSingleInstanceApp::GetSecondInstanceCmdLine()
method to get the second instance command line.
class CMyApp : public /*CWinApp*/ CSingleInstanceApp { // ... };
CMyApp::CMyApp() :
CSingleInstanceApp(TEXT("{49E4CD26-9489-4474-91B0-2A30F6CA3097}"))
Please note, that argument to CSingleInstanceApp
constructor must be the
pointer to the system unique string (it is used to name the file mapping
and to register the window message). Replace it with newly generated GUID.
BOOL CMyApp::InitInstance() { if (!AmITheFirst()) return false; // ...
Using the code without MFC
It's also very simple.
-
Define
UINT
variable andSingleInstanceApp
instance like this: -
Having
single
defined at the global scope add the check at yourWinMain
function: -
Optional. Registered message posted by
PostThreadMessage()
function can't be dispatched to a window procedure. So, add the code to your application message loop to get notified when the second instance is being tried to start. You can use here theSingleInstanceApp::GetSecondInstanceCmdLine()
method to get the second instance command line:
UINT uSecondInstanceMessage;
SingleInstanceApp single(TEXT(
"{B0C9E56F-687A-4c1f-9862-2F4D0F748827}"),
uSecondInstanceMessage);
These two must be accessible from scope of the application message loop. The easiest way to do this is to define it at the global scope.
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { if (!single.AmITheFirst()) return false; // ...
while (GetMessage(&msg, NULL, 0, 0)) { if (uSecondInstanceMessage == msg.message) { // add your code here continue; } // ...
That's all folks :)