Single instance applications are fun in any programming language. Let's take QT as example. One could just create a server and depending on whether it can listen, determine if another instance is running. Something like this:
Codeserver = new QLocalServer();
bool serverListening = server.listen("SomeName");
if (!serverListening) {
//hey, I'm walkin over here
}
And that's it. Only if it would be this easy.
This code might fail on Unix with AddressInUseError if there was a previous application crash. This means we need to complicate code a bit:
Codeserver = new QLocalServer();
bool serverListening = server.listen("SomeName");
if (!serverListening && (server->serverError() == QAbstractSocket::AddressInUseError)) {
QLocalServer::removeServer(serverName); //cleanup
serverListening = _server->listen(serverName); //try again
}
if (!serverListening) {
//hey, I'm walkin over here
}
But fun wouldn't be complete if that was all. You see, Windows have issues of their own. As implemented in QT, you can actually have multiple listeners at the same time. Failure to listen will never happen there.
Unfortunately this is a bit more complicated and you can really go wild solving this issue - even so far as to involve QSystemSemaphore with it's portability and thread blocking issues.
Or you can go with solution that works 99% of the time - directly calling into CreateMutexW API.
Modifying code in the following manner will do the trick:
Codeserver = new QLocalServer();
bool serverListening = server.listen("SomeName");
if (!serverListening && (server->serverError() == QAbstractSocket::AddressInUseError)) {
QLocalServer::removeServer(serverName); //cleanup
serverListening = _server->listen(serverName); //try again
}
#if defined(Q_OS_WIN)
if (serverListening) {
CreateMutexW(nullptr, true, reinterpret_cast<LPCWSTR>(serverName.utf16()));
if (GetLastError() == ERROR_ALREADY_EXISTS) { //someone has this Mutex
server->close(); //disable server
serverListening = false;
}
}
#endif
if (!serverListening) {
//hey, I'm walkin over here
}
Now on Windows we try to create our very own mutex. If that succeeds, all is normal. If that returns an error, we simply close our server because we know some other instance owns the mutex.
Not ideal but it covers single-instance scenario reasonably well.
If you want to use this in application, you can download the example and use it as follows:
Codeif (!SingleInstance::attach()) {
return static_cast<int>(0x80004004); //exit immediately if another instance is running
}
When trying to use it I got:
Undefined symbols for architecture x86_64:
“SingleInstance::newInstanceDetected()”, referenced from:
SingleInstance::onNewConnection() in singleinstance.cpp.o
“vtable for SingleInstance”, referenced from:
SingleInstance::SingleInstance() in singleinstance.cpp.o
SingleInstance::~SingleInstance() in singleinstance.cpp.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Can’t figure out why