Qt之运行一个实例进程

简述

发布程序的时候,我们往往会遇到这种情况:

  1. 只需要用户运行一个实例进程
  2. 用户可以同时运行多个实例进程

一个实例进程的软件有很多,例如:360、酷狗…
多个实例进程的软件也很多,例如:Visual Studio、Qt Ctretor、QQ…

下面我们来介绍下如何实现一个实例进程。

  • 简述
  • QSharedMemory
  • QLocalServer
  • QtSingleApplication
  • 任务列表
  • 更多参考

QSharedMemory

使用共享内存来实现,key值唯一,一般可以用组织名+应用名来确定。

首先,创建一个共享内存区,当第二个进程启动时,判断内存区数据是否建立,如果有,可以激活已打开的窗体,也可以退出。

当程序crash的时候,不能及时清除共享区数据,导致程序以后不能正常启动。

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    QCoreApplication::setOrganizationName("Company");
    QCoreApplication::setApplicationName("AppName");
    QString strKey = QCoreApplication::organizationName() + QCoreApplication::applicationName();

    QSharedMemory sharedMemory(strKey);
    if (!sharedMemory.create(512, QSharedMemory::ReadWrite))
    {
        QMessageBox::information(NULL, QStringLiteral("提示"), QStringLiteral("程序已运行!"));
        exit(0);
    }

    MainWindow window;
    window.show();

    return app.exec();
}

QLocalServer

QSingleApplication.h

#ifndef SINGLE_APPLICATION_H
#define SINGLE_APPLICATION_H

#include <QApplication>

class QLocalServer;

class QSingleApplication : public QApplication
{
    Q_OBJECT

public:
    explicit QSingleApplication(int argc, char **argv);
    // 判断进程是否存在
    bool isRunning();

private slots:
    void newLocalConnection();

private:
    QLocalServer *m_pServer;
    bool m_bRunning;
};

#endif // SINGLE_APPLICATION_H

QSingleApplication.cpp

#include <QLocalSocket>
#include <QLocalServer>
#include <QFile>
#include <QTextStream>
#include "QSingleApplication.h"

QSingleApplication::QSingleApplication(int argc, char **argv)
    : QApplication(argc, argv),
      m_bRunning(false)
{
    QCoreApplication::setOrganizationName("Company");
    QCoreApplication::setApplicationName("AppName");
    QString strServerName = QCoreApplication::organizationName() + QCoreApplication::applicationName();

    QLocalSocket socket;
    socket.connectToServer(strServerName);

    if (socket.waitForConnected(500))
    {
        QTextStream stream(&socket);
        QStringList args = QCoreApplication::arguments();

        QString strArg = (args.count() > 1) ? args.last() : "";
        stream << strArg;
        stream.flush();
        qDebug() << "Have already connected to server.";

        socket.waitForBytesWritten();

        m_bRunning = true;
    }
    else
    {
        // 如果不能连接到服务器,则创建一个
        m_pServer = new QLocalServer(this);
        connect(m_pServer, SIGNAL(newConnection()), this, SLOT(newLocalConnection()));

        if (m_pServer->listen(strServerName))
        {
            // 防止程序崩溃,残留进程服务,直接移除
            if ((m_pServer->serverError() == QAbstractSocket::AddressInUseError) && QFile::exists(m_pServer->serverName()))
            {
                QFile::remove(m_pServer->serverName());
                m_pServer->listen(strServerName);
            }
        }
    }
}

void QSingleApplication::newLocalConnection()
{
    QLocalSocket *pSocket = m_pServer->nextPendingConnection();
    if (pSocket != NULL)
    {
        pSocket->waitForReadyRead(1000);

        QTextStream in(pSocket);
        QString strValue;
        in >> strValue;
        qDebug() << QString("The value is: %1").arg(strValue);

        delete pSocket;
        pSocket = NULL;
    }
}

bool QSingleApplication::isRunning()
{
    return m_bRunning;
}

使用方式

int main(int argc, char **argv)
{
    QSingleApplication app(argc,argv);
    if (app.isRunning())
    {
        QMessageBox::information(NULL, QStringLiteral("提示"), QStringLiteral("程序已运行!"));
        exit(0);
    }

    MainWindow window;
    window.show();

    return app.exec();
}

QtSingleApplication

QSingleApplication位于qt-solution里面,并不包含在Qt库中,遵循 LGPL 协议。

文档、源码、示例见:QtSingleApplication

任务列表

运行程序时,遍历任务列表,查看是当前所有运行中的进程,如果当前进程位置在映射路径中可以找到,则说明程序已经运行,否则,未运行。

更多参考

时间: 2024-08-07 17:10:44

Qt之运行一个实例进程的相关文章

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

起因 最近想实现一个应用程序单例化的程序, 目前使QT运行一个实例有如下几种方式 1.QSharedMemory 使用共享内存,当第二个进程启动时,判断内存区数据是否建立,如有,则退出; 这种方式有弊端,在程序发生崩溃时,未及时清除共享区数据,导致程序不能正常启动. 2.文件锁 在程序运行的时候就在目录下创建一个文件,当程序运行时就判断这个文件是否存在,如果存在说明程序已经在运行.其本质与QSharedMemory相同 3.利用QLocalServer 参照 Qt实现应用程序单实例运行–Loca

实现只能运行一个实例,当第二次双击程序运行时把第一个激活并传递参数进去

问题描述 using Microsoft.VisualBasic.ApplicationServices; staticvoidMain(string[]args) { AppmyApp=newApp(); myApp.Run(args); } classApp:WindowsFormsApplicationBase { publicApp() { //设置单例模式 this.IsSingleInstance=true; //设置可用于XP窗口样式 this.EnableVisualStyles

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

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

如何让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

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

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

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

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

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