天天看点

Qt中单例程序的实现

       有的时候我们编写的项目,需要单例运行的功能,也就是同时只能运行一个该程序(默认程序是可以启动多个,同时运行的),之前写了一篇博客,探讨在Qt中注册系统热键的实现。单例运行功能和注册系统热键一样,都是通过windows API实现的,简而言之就是代码跟Qt库没有任何关系,但可以运用到Qt程序中。

       先说一下基本原理:通过CreateToolhelp32Snapshot(DWORD dwFlags,DWORD th32ProcessID)函数获得所有进程的快照,这个函数的返回值是一个HANDLE,通过HANDLE遍历所有进程的信息并存储到结构体PROCESSENTRY32中。访问该结构体的szExeFile就可以获得进程名。判断获得的进程名与本程序名是否相同,相同就进行计数。当数量为2或2以上时程序自动结束(执行代码时程序已经运行,所以单例运行的情况下该数量应该为1)。代码如下:

#include "dialog.h"
#include <QApplication>
#include <windows.h>      //单例代码必须的头文件。
#include <tlhelp32.h>     //单例代码必须的头文件。
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //单例判断。
    HANDLE proSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);  //TH32CS_SNAPPROCESS表示在快照中包含系统中所有的进程。
    PROCESSENTRY32 proEntry = {0};
    proEntry.dwSize = sizeof(PROCESSENTRY32);    //初始化结构体大小。没有这一句Process32First()会失败。
    bool exist = Process32First(proSnap, &proEntry);    //获得HANDLE中的第一个进程信息,如果成功,返回true,否则false。
    int count = 0;    //用于计数的变量。
    while(exist)    //读取进程信息。
    {
        QString file = QString::fromWCharArray(proEntry.szExeFile);    //获得当前进程名并转化为QString类型。
        if (QApplication::applicationName()+".exe" == file)    //进行判断,如果同名就计数。
            count++;
        exist = Process32Next(proSnap, &proEntry);    //获取下一个进程信息,成功返回true,否则返回false。
    }
    CloseHandle(proSnap);    //关闭HANDLE。
    if (count >= 2)    //如果本程序已经在运行,再启动程序时count就会大于等于2,因此结束本程序,保证程序单例运行。
        return 0;
    
        /**********************以下是程序正常执行的代码**********************/
    Dialog w;
    return a.exec();
}
           

       最后是示例程序:http://download.csdn.net/detail/u012952807/9596563

继续阅读