Qt/C++ - Lesson 043. Qt Single Application - Start only one instance of application

QLockFile, QSharedMemory, QSystemSemaphore, Qt, Qt Single Application

Permission to run only one instance of the application may be necessary to limit the problems with memory leaks, or to eliminate possible problems with the competition between two instances of an application for some resources, files, SQLite database, etc. Or if, in principle, the application requires only one copy is used by the user.

Two methods can be used to solve this problem:

  • Using QLockFile - when a temporary file is created, which is destroyed when the application is closed. Thus at the second instance of the application starts happening on the existence of the file and check if the file already created one open application instance, the second instance is automatically closed;
  • Using QSystemSemaphore and QSharedMemory - in this case creates a shared memory segment and tries to connect it to an existing segment with a unique identifier. If the connection attempt is successful, then one instance of the application has already been created. Accordingly, we inform the user about it and close the application. If the connection attempt is unsuccessful, then we select create memory segment for the application and run the first instance.

The rest of the code will not go beyond main.cpp.

Single application using QLockFile

In the following code in the folder for temporary files created during application startup Lock File, in the case of an unsuccessful attempt to create a Lock File, the program assumes that is already open one instance of the application, notify the user and closes.

Note. Replace <uniq id> on your ID.

#include "widget.h"
#include <QApplication>
#include <QLockFile>
#include <QDir>
#include <QMessageBox>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QLockFile lockFile(QDir::temp().absoluteFilePath("<uniq id>.lock"));

    /* Trying to close the Lock File, if the attempt is unsuccessful for 100 milliseconds, 
     * then there is a Lock File already created by another process. 
     / Therefore, we throw a warning and close the program
     * */
    if(!lockFile.tryLock(100)){
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Warning);
        msgBox.setText("The application is already running.\n"
                       "Allowed to run only one instance of the application.");
        msgBox.exec();
        return 1;
    }

    Widget w;
    w.show();

    return a.exec();
}

Single application using QSystemSemaphore and QSharedMemory

In a first variant, it is given a simple and convenient solution to the problem by limiting the number of running instances of Qt applications. But the decision on QLockFile has disadvantages in the sense that there may be a problem with the permissions of the user. And also, if you want to limit, run a single instance of the program for the entire computer, not the differences, how many user sessions can be run on it, then use QLockFile also does not provide this capability.

QSharedMemory the contrary is shared for all users at the same time working at a computer. Therefore, if one of your users to run the program, the latter will not be able to run it.

But in this case, it is necessary not to forget about the differences in the shared memory by the various platforms. In the case with Windows , shared memory will be freed when a normal completion of the program, and at the end of the emergency. In the case of Linux/Unix in case of emergency when crashes memory will not be freed.

The semaphore code presented below is used to solve the problem of race in the case of the simultaneous launch of multiple instances of the same application. The semaphore is created with the meter, the maximum number of which is equal to 1. When lifting the semaphore, all other instances of the application does not have access to the shared memory and thus one copy of wholly owned resources. This copy checks for running another instance of the application by the presence of a shared memory segment identifier corresponding to the application. A copy of the shared memory segment was successfully launched and creates if not found information about another application instance. After that, the semaphore is lowered, allowing another instance of the application tried to run.

Note. Replace <uniq id> and <uniq id2> on your ID.

#include "mainwindow.h"
#include <QApplication>
#include <QSystemSemaphore>
#include <QSharedMemory>
#include <QMessageBox>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QSystemSemaphore semaphore("<uniq id>", 1);  // create semaphore
    semaphore.acquire(); // Raise the semaphore, barring other instances to work with shared memory

#ifndef Q_OS_WIN32
    // in linux / unix shared memory is not freed when the application terminates abnormally,
    // so you need to get rid of the garbage
    QSharedMemory nix_fix_shared_memory("<uniq id 2>");
    if(nix_fix_shared_memory.attach()){
        nix_fix_shared_memory.detach();
    }
#endif

    QSharedMemory sharedMemory("<uniq id 2>");  // Create a copy of the shared memory
    bool is_running;            // variable to test the already running application
    if (sharedMemory.attach()){ // We are trying to attach a copy of the shared memory
                                // To an existing segment
        is_running = true;      // If successful, it determines that there is already a running instance
    }else{
        sharedMemory.create(1); // Otherwise allocate 1 byte of memory
        is_running = false;     // And determines that another instance is not running
    }
    semaphore.release();       

    // If you already run one instance of the application, then we inform the user about it
    // and complete the current instance of the application
    if(is_running){
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Warning);
        msgBox.setText("The application is already running.\n" 
                       "Allowed to run only one instance of the application.");
        msgBox.exec();
        return 1;
    }

    MainWindow w;
    w.show();

    return a.exec();
}

Video

Virtual hosting with 10 percent discount
Virtual hosting with 10 percent discount
EVILEG offers reliable hosting with a 10% discount for virtual hosting and 5% for VPS
Support the author Donate

День добрый.
Подскажите, как с помощью этих примеров вместо вывода сообщения сделать активным окно запущенного экземпляра приложения?

Добрый день!

С помощью API целевой системы придётся найти нужный процесс и открыть окно. Но придётся писать платформозависимый код. В случае Windows нужно смотреть, как с помощью WinAPI искать процессы и пытаться открыть их окна, если они есть. В случае Linux там ещё сложнее, или через XLib, или через DBus, но я не уверен, как именно это делается.

Понятно. Спасибо!

Comments

Only authorized users can post comments.
Please, Log in or Sign up
TT
June 13, 2019, 7:01 p.m.
Taimoor Tanweer

C++ - Test 001. The first program and data types

  • Result:66points,
  • Rating points-1
TT
June 13, 2019, 6:51 p.m.
Taimoor Tanweer

C++ - Test 002. Constants

  • Result:75points,
  • Rating points2
ВМ
June 13, 2019, 12:30 p.m.
Ваня Мороз

C++ - Test 001. The first program and data types

  • Result:100points,
  • Rating points10
Last comments
i
June 17, 2019, 6:10 a.m.
ingenfly

Только по осям xAxis2, уAxis2 значения начинаются с 0. Почему-то xAxis2 и xAxis не синхронизированы по данным. Ну и QCustomPlot последний.
June 16, 2019, 8:21 p.m.
Евгений Легоцкой

Добрый день. Ну точно также добавляете ту же самую информацию на ось xAxis2, только добавляете другое форматирование customPlot->xAxis2->setDateTimeFormat("hh:mm"); если я ...
EF
June 14, 2019, 1:56 p.m.
Egor Fomin

Спасибо за ваш ответ, у меня получилось реализовать это. Тем не менее появилась другая проблема, поэтому опять надеюсь на вашу помощь. Скажем, я уже выставил точки и они соеденены. Когда я нач...
d
June 13, 2019, 2:47 p.m.
damix

Можно классу, который описывает точку, добавить сигнал, который подавать (emit), когда точка перемещается (переопределить mouseMoveEvent или mouseReleaseEvent). Так вот эти сигналы у каждой из...
i
June 13, 2019, 2:09 p.m.
ingenfly

Здравствайте! Подскажите, пожалуйста: customPlot->xAxis2->setTickLabels(true); //Здесь включается отображение данных на оси xAxis2. а можно как-то продублировать информацию cus...
Now discuss on the forum
June 20, 2019, 9:30 a.m.
IscanderChe

Вернулся к этой задачке только-только, поэтому и не ответил ничего раньше.Как переопределить mouseReleaseEvent(QMouseEvent* event) у QTableView, если QTableView задан в ui? Или задавать QTabl...
I
June 19, 2019, 1:41 p.m.
Intruder

Всем добрый день. При разборе XML файла наткнулся на тег вот такого плана: <TagName attribute1="value1" attribute2="value2" /> При попытке проверить на наличие такого элеме...
June 19, 2019, 12:55 p.m.
Михаиллл

Скажите пожалуйста, как его в таком случае перемещать и удалять?
June 18, 2019, 7:50 p.m.
Дмитрий

Большое спасибо! SDK заработал.К сожалению удалось продвинутся только на один шаг. При сборке чистого проекта NDK выдаёт следующие ошибки C:\Android\ndk-bundle/toolchains/arm-linux-andr...
June 18, 2019, 4:59 p.m.
Михаиллл

Добрый день.В этом учебнике представлен код INSTALLED_APPS = ( ... 'rest_framework', 'snippets.apps.SnippetsConfig',) На строчке 'snippets.apps.SnippetsConf...
Looking for a Job?
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

For registered users on the site there is a minimum amount of advertising

EVILEG
About
Services
Join us
© EVILEG 2015-2019
Recommend hosting TIMEWEB