QT中实现程序只运行一个实例--应用程序的单例化

起因



最近想实现一个应用程序单例化的程序,

目前使QT运行一个实例有如下几种方式

1.QSharedMemory
使用共享内存,当第二个进程启动时,判断内存区数据是否建立,如有,则退出; 这种方式有弊端,在程序发生崩溃时,未及时清除共享区数据,导致程序不能正常启动.

2.文件锁
在程序运行的时候就在目录下创建一个文件,当程序运行时就判断这个文件是否存在,如果存在说明程序已经在运行。其本质与QSharedMemory相同

3.利用QLocalServer
参照
Qt实现应用程序单实例运行–LocalServer方式
让QT只运行一个实例

4.QtSingleApplication
使用QT扩展库QtSingleApplication,能很好的解决这个问题.
QSingleApplication 是 Qt 提供的一个 solution ,它不包含在 Qt 的 library 中。遵循 LGPL 协议。关于如何使用,下载了这个 solution 之后,里面有例子。还有, QtCreator 中还用到了它。你也可以翻一番 QtCreator 的源代码。
里面就是用的QLocalServer/QLocalSocket建立本地socket来判断实例是否存在
在看到可以通过编写一个SingleApplication类来实现。

它提供了两个SingleApplication类,第一个用QSharedMemory, QLocalServer 和 QLocalSocket实现,第二个用QSharedMemory和QTimer实现,具体代码网页说明得很清楚,怎么使用也有代码示例。我自己也将代码做了测试,第二个类被我改成SingleApplication2。

编译之后,运行。找到编译出来的文件,再运行一次就可以看到效果了。两个SingleApplication类都用了Qt的共享内存,不同之处在于程序实例之间的通信(也就是程序第二个实例通知程序的第一个实例用户又一次运行了本程序,此时第一个实例可以做出相应的相应)用的方式不同。

如果两个程序实例之间直接不需要通信,那么直接使用共享内存实现就可以了,不需要QLocalServer 和 QLocalSocket或者QTimer。

使用qtsingleapplication实现qt程序单例


使用qtsingleapplication



使用QtSingleApplication 代替原来的QApplication类
该单例类中有一个isRunning()方法来判断当前程序是否在运行
因此使用方法如下

引入项目



将里面的qtsingleapplication目录拷贝到项目的源码目录中,

然后修改项目的.pro文件,引入加入qtsingleapplication工程,下面一行代码

include(../qtsingleapplication/src/qtsingleapplication.pri)

QtSingleApplication 代替原来的QApplication类



修改main.cpp文件,加入头文件

#include <QtSingleApplication>
  • 1
  • 1

并且修改QtSingleApplication 代替原来的QApplication类

#include <QApplication>
#include <QtSingleApplication>
#include <QMessageBox>

int main(int argc, char *argv[])
{
    QtSingleApplication app(argc, argv);
    if (app.isRunning())
    {
        QMessageBox::information(NULL, "GLMPlayer",
                                 "Your GLMPLayer is already running ...",
                         QMessageBox::Ok);
        app.sendMessage("raise_window_noop");
        return EXIT_SUCCESS;
    }

    SingleApplication w;
    w.show();

    return app.exec();
}

默认情况下,QtSingleApplication使用QApplication::applicationFilePath作为自己的appId,用于识别不同的app

如果希望不受程序存放路径影响,则需要在指定appId即可。如下

 QtSingleApplication app(QLatin1String("my_app_id"),argc, argv);

这样即便是在不同的目录的程序,仍能互斥

发送消息和激活窗口



收发消息是QtSingleApplication特有的功能,而QApplication是不具有的。

默认情况下,QtSingleApplication接收到任何消息之后,都会自身的窗口窗口。如果不希望激活窗口,则可以自行设定,甚至重新连接信号槽。如下

app.setActivationWindow(&w,false); 

QObject::connect(&app, SIGNAL(messageReceived(const QString&)),&w, SLOT(handleMessage(const QString&))); 

时间: 2024-09-19 09:32:24

QT中实现程序只运行一个实例--应用程序的单例化的相关文章

如何让VC和Delphi程序只运行一个实例

有些时候,我们需要我们的程序只运行一个实例,笔者自己作程序也有这样的情况,于是自已探究一番.忙活一阵后,总算小有收获,不敢独享,在天极发表出来,供大家参考. 既然是从根本上解决问题,对于Windows程序而言,就从WinMain函数入口,这是因为在VC中使用SDK的方式编写程序最透明,并且WinMain是作为VC编译器生成EXE文件的默认入口函数. WinMain的函数原型: int WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, L

如何使应用程序只运行一个实例

要使应用程序只运行一个实例,一个简单的方法是在应用程序类中使用互斥量,这可以用VC下的GUIDGEN.EXE程序产生.GUIDGEN.EXE位于VC安装目录CommonTools目录下 实例 1: 新建一基于对话框的工程ex1,采用默认设置 2: 用GUIDGEN.EXE产生一个全局标志,#define one "产生的全局标志" 本例中产生的语句如下:#define one "0xbe8e2ce1, 0xdab6, 0x11d6, 0xad, 0xd0, 0x0, 0xe0

让C#程序只运行一个实例,显示已经运行的界面

让程序只运行一个实例的方法一: static void Main()         {             System.Threading.Mutex mutex;             bool isNew;             mutex = new System.Threading.Mutex(true, "myproject", out isNew);             if (isNew)             {                 App

程序只运行一个实例,并激活前一个实例

示例代码运行效果图如下: 实现程序只运行一次的方法很多,但是原理都是一样的,就是运行第一次的时候设置一个标记,每次运行的时候检查该标记,如果有就说明已经运行了. 具体实现: 1.在程序初始化的时候 (InitInstance()) 枚举所有的窗口,查找本程序的实例是否存在 2.在主窗口初始化的时候在本窗口的属性列表中添加一个标记,以便程序查找. 部分关键代码 1.在App的InitInstance()中枚举所有窗口,查找本程序实例 HWND oldHWnd = NULL; EnumWindows

wpf只运行一个实例

原文:wpf只运行一个实例在winform下,只运行一个实例只需这样就可以: 1. 首先要添加如下的namespace: using System.Threading; 2. 修改系统Main函数,大致如下:         bool bCreatedNew;               //Create a new mutex using specific mutex name         Mutex m =new Mutex( false, "myUniqueName", ou

WinForm限制客户程序只能运行一个实例

WinForm限制客户程序只能运行一个实例: using System; using System.Threading; static void Main() { bool create = false; using (Mutex mu = new Mutex(true, Application.ProductName, out create)) { if (create) { Application.Run( new MainForm() ); } else { MessageBox.Show

bat脚本实例实现只允许运行一个实例(安装程序、创建快捷方式脚本)_DOS/BAT

复制代码 代码如下: ;我的第一个安装脚本!include "MUI2.nsh"!define DIR "D:\workspace\nsis\files" Name "安装程序"Icon "${DIR}\setup128.ico"OutFile "setup.exe"InstallDir "$PROGRAMFILES\kaserv"RequestExecutionLevel admin

只运行一个实例,单击程序快捷方式让程序激活到前台

程序|快捷方式 涉及类: 1. 启动画面类: public class SplashForm : System.Windows.Forms.Form { private System.Windows.Forms.PictureBox pictureBox1; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label lbl_version; /// /// 必需的设计器变量. /// private

只运行一个实例且试图运行第二个实例时自动激活第一个实例

本文配套源码 很多程序象winamp,TTplayer,RealPlayer等都有自动激活前一个实例的功能,其实这玩意也很简单的 ,在VB中可以用App.hInstance 来判断是否运行了程序的一个实例,用API函数FindWindow来找到前一个 实例的句柄,从而为激活她做好了准备.但是App.hInstance 有很大的局限性,一个不需要其他资源支 持的EXE文件,如果你复制到其他目录,这个复制品就可以畅通无阻的运行而不管他的前辈是否已运行, 如果这个程序需要独占某个硬件或其他资源,这样就