如何用Qt写一个同一时间只能运行一个实例的应用程序
2013-08-29 16:55
375 查看
http://blog.sina.com.cn/s/blog_6343941a0100nk2x.html
可以达到的目的:
1、应用只启动一个实例,依赖于QtNetwork模块
2、启动时向另一个实例通信
下载地址:http://qt.gitorious.org/qt-solutions/qt-solutions/archive-tarball/master
解压开后,将里面的qtsingleapplication目录拷贝到项目的源码目录中,然后修改项目的.pro文件,加入下面一行代码
==============
include(../qtsingleapplication/src/qtsingleapplication.pri)
==============
修改main.cpp文件,加入头文件
#include <QtSingleApplication>
main函数实现:
===================================
QtSingleApplication app(argc, argv);
if (app.isRunning())
{
app.sendMessage("raies");
return EXIT_SUCCESS;
}
........
QMainWindow w;
app.setActivationWindow(&w);
.......
===================================
为了使一个应用程序在同一时间只运行一个实例,需要用某种方法在程序启动时,检测是否已有正在运行的实例,如果有,则将本次启动的参数传递给前一个实例(例如需要打开的文档的路径),如果没有,则正常启动。
实现的方法有多种:
1. 用Windows API创建一个互斥量:
注:如果保险起见,CreateMutex()中的字符串应该用一个GUID来保证其唯一性,Visual Studio中有一个生成GUID的工具,菜单“工具”->“创建GUID”,选择合适的定义形式,创建并拷贝到剪贴板即可。
此方法的缺点:1.使用了Windows API,不能跨平台;2.不能自动激活前一个实例的窗口。
2. 每次启动时用Windows API枚举进程,同时在第一次运行时用SetProp()函数给当前窗口设置属性,这样下次启动时,在枚举的进程中查找具有这个属性的窗口,若找到,说明已有实例在运行,将该实例的窗口激活;若未找到则正常启动。
此方法客服了前一方法的第2个缺点,但过于依赖Windows API函数(似乎还是MFC函数,对Qt程序好像不可行)。有兴趣的可以照这个链接里的代码试试
3. 利用QLocalSocket和QLocalServer,基本的思路是:
应用程序启动时首先尝试去连接一个QLocalServer,如果连接失败,说明自己是第一个实例,于是创建这么一个QLocalServer,否则将启动参数发送给QLocalServer然后退出。第一个实例的QLocalServer在收到后面启动的实例发来的参数时可以进行处理(例如激活第一个实例的窗口)。这个链接里有详细的示例代码供参考。
注:使用QLocalSocket和QLocalServer时,需要把QtNetwork库包含在项目文件中;
4. 用Qt Solutions里提供的QtSingleApplication类(最简单的方法,推荐)
从ftp://ftp.qt.nokia.com/qt/solutions/lgpl/ 下载QtSingleApplication的源码包,解压缩后按照INSTALL.TXT里的说明进行配置和编译,我选择编译成动态库,这样下次再用,只需引用头文件和lib文件即可,比较方便。
用法很简单,只需把原来main()里的QApplication对象换成QtSingleApplication对象,调用一下isRunning()方法进行判断即可。
注1:QtSingleApplication的实现方法基本上也是利用QLocalServer和QLocalSocket,所以同样依赖于QtNetwork库;
注2:以上代码只展示了QtSingleApplication最简单的用法,这个类还有更多用法,请参考源码包中带的范例和文档。
QtSingleApplication的几种用法(直接使用源码,编译成动态库等)可以参考这个链接:Qt程序只运行一个实例
可以达到的目的:
1、应用只启动一个实例,依赖于QtNetwork模块
2、启动时向另一个实例通信
下载地址:http://qt.gitorious.org/qt-solutions/qt-solutions/archive-tarball/master
解压开后,将里面的qtsingleapplication目录拷贝到项目的源码目录中,然后修改项目的.pro文件,加入下面一行代码
==============
include(../qtsingleapplication/src/qtsingleapplication.pri)
==============
修改main.cpp文件,加入头文件
#include <QtSingleApplication>
main函数实现:
===================================
QtSingleApplication app(argc, argv);
if (app.isRunning())
{
app.sendMessage("raies");
return EXIT_SUCCESS;
}
........
QMainWindow w;
app.setActivationWindow(&w);
.......
===================================
为了使一个应用程序在同一时间只运行一个实例,需要用某种方法在程序启动时,检测是否已有正在运行的实例,如果有,则将本次启动的参数传递给前一个实例(例如需要打开的文档的路径),如果没有,则正常启动。
实现的方法有多种:
1. 用Windows API创建一个互斥量:
#include <windows.h> int main(int argc, char *argv[]) { QApplication a(argc, argv); HANDLE hMutex = CreateMutex(NULL, TRUE, L"YourApp"); // 创建一个互斥量来保证只运行一个实例 if(hMutex != NULL) { if(GetLastError() == ERROR_ALREADY_EXISTS) { QMessageBox::critical(qApp->activeWindow(), QObject::tr("An instance of this application has been run!"), QObject::tr("Only one instance can be run at a time!")); return 1; } } ... // 以下是正常启动代码 }
注:如果保险起见,CreateMutex()中的字符串应该用一个GUID来保证其唯一性,Visual Studio中有一个生成GUID的工具,菜单“工具”->“创建GUID”,选择合适的定义形式,创建并拷贝到剪贴板即可。
此方法的缺点:1.使用了Windows API,不能跨平台;2.不能自动激活前一个实例的窗口。
2. 每次启动时用Windows API枚举进程,同时在第一次运行时用SetProp()函数给当前窗口设置属性,这样下次启动时,在枚举的进程中查找具有这个属性的窗口,若找到,说明已有实例在运行,将该实例的窗口激活;若未找到则正常启动。
此方法客服了前一方法的第2个缺点,但过于依赖Windows API函数(似乎还是MFC函数,对Qt程序好像不可行)。有兴趣的可以照这个链接里的代码试试
3. 利用QLocalSocket和QLocalServer,基本的思路是:
应用程序启动时首先尝试去连接一个QLocalServer,如果连接失败,说明自己是第一个实例,于是创建这么一个QLocalServer,否则将启动参数发送给QLocalServer然后退出。第一个实例的QLocalServer在收到后面启动的实例发来的参数时可以进行处理(例如激活第一个实例的窗口)。这个链接里有详细的示例代码供参考。
注:使用QLocalSocket和QLocalServer时,需要把QtNetwork库包含在项目文件中;
4. 用Qt Solutions里提供的QtSingleApplication类(最简单的方法,推荐)
从ftp://ftp.qt.nokia.com/qt/solutions/lgpl/ 下载QtSingleApplication的源码包,解压缩后按照INSTALL.TXT里的说明进行配置和编译,我选择编译成动态库,这样下次再用,只需引用头文件和lib文件即可,比较方便。
用法很简单,只需把原来main()里的QApplication对象换成QtSingleApplication对象,调用一下isRunning()方法进行判断即可。
// 原来的代码 int main(int argc, char **argv) { QApplication app(argc, argv); MyMainWidget mmw; mmw.show(); return app.exec(); } // 修改后的代码 int main(int argc, char **argv) { QtSingleApplication app(argc, argv); if (app.isRunning()) return 0; MyMainWidget mmw; mmw.show(); return app.exec(); }
注1:QtSingleApplication的实现方法基本上也是利用QLocalServer和QLocalSocket,所以同样依赖于QtNetwork库;
注2:以上代码只展示了QtSingleApplication最简单的用法,这个类还有更多用法,请参考源码包中带的范例和文档。
QtSingleApplication的几种用法(直接使用源码,编译成动态库等)可以参考这个链接:Qt程序只运行一个实例
相关文章推荐
- 如何用Qt写一个同一时间只能运行一个实例的应用程序
- QT中实现程序只运行一个实例--应用程序的单例化
- 如何让应用程序仅运行一个实例(c#)
- 如何让应用程序只有一个实例在运行?
- 应用程序每次只能运行一个实例(C#)
- 关于"如何让应用程序只有一个实例在运行"的孟宪会的解决方法的疑问
- 如何确保只有一个应用程序实例在运行?
- 如何让Qt应用程序只有一个实例
- 使Qt 程序只能运行一个实例的3种方法
- 如何使应用程序只有一个实例在运行
- 如何使应用程序只运行一个实例
- 如何让应用程序只有一个实例在运行?
- 使应用程序只能运行一个实例
- 如何使应用程序只运行一个实例
- 如何使应用程序只运行一个实例
- 如何使应用程序只运行一个实例
- C#[Win32&WinCE&WM]应用程序只能运行一个实例:MutexHelper
- 使Qt程序只能运行一个实例的3种方法
- Oracle 远程访问配置 在 Windows Forms 和 WPF 应用中使用 FontAwesome 图标 C#反序列化XML异常:在 XML文档(0, 0)中有一个错误“缺少根元素” C#[Win32&WinCE&WM]应用程序只能运行一个实例:MutexHelper Decimal类型截取保留N位小数向上取, Decimal类型截取保留N位小数并且不进行四舍五入操作
- (转)如何使应用程序只运行一个实例