当前位置:   article > 正文

QT笔记:同类型程序只能运行一个_qt程序只能运行一次

qt程序只能运行一次

由于NSIS实现自定义界面,以及把安装包和升级包合并太过复杂,在各种尝试失败之后决定自己写安装包和卸载包。

原本项目中已经有一个让程序只运行一次的代码,使用QSystemSemaphore和QSharedMemory实现的。

  1. QSystemSemaphore sema("Key",1,QSystemSemaphore::Open);
  2. sema.acquire();//在临界区操作共享内存 SharedMemory
  3. QSharedMemory mem("Object");//全局对象名
  4. if (!mem.create(1))//如果全局对象以存在则退出
  5. {
  6. NDialog dialog(QApplication::focusWidget());
  7. NMessageBox Msg(&dialog,NMessageBox::ErrMsg,QObject::tr("软件运行中,再次打开前请先关闭。"));//获取最后一条错误信息
  8. dialog.setWidget(&Msg,QObject::tr("软件打开错误"));
  9. dialog.exec();
  10. sema.release();
  11. return 0;
  12. }
  13. sema.release();

 

但后来发现,这段代码只支持同时运行两个程序,当第三个程序运行时,只会在后台出现,不会有任何界面提示,即使把前两个程序关闭也不行。直到打开任务管理器,把所有程序全部结束掉,再打开才能正常使用。

这种场景在日常使用并不常见,但是如果加入安装/卸载程序,三种程序都用这种方式,出现的概率就大很多,于是引入QtSingleApplication。

由于使用pri文件方式在修改代码时出现了问题(也可能是配置问题),实在懒得深究了,就直接把代码添加到目录里面了。

  1. 下载qtsingleapplication压缩包,并解压。
  2. 在项目文件夹中新建两个文件夹qtlockedfile和qtsingleapplication
  3. 将qtsinglecoreapplication.cpp/.h、qtsingleapplication.cpp/.h、qtlocalpeer.cpp/.h 共6个文件,放到qtsingleapplication文件夹
  4. 将qtlockedfile.cpp/.h、qtlockedfile_win.cpp、qtlockedfile_unix.cpp 共4个文件,放到qtlockedfile文件夹
  5. 将上面的qtsingleapplication文件夹中所有文件,以及qtlockedfile文件夹中的qtlockedfile.cpp/.h文件,共8个文件全部添加到项目中
  6. 在.pro文件中添加
    1. win32 {
    2. SOURCES += qtlockedfile/qtlockedfile_win.cpp
    3. }
    4. unix {
    5. SOURCES +=qtlockedfile/qtlockedfile_unix.cpp
    6. }

     

  7. 在代码的main.cpp中,将原来的
    1. #include <QApplication>
    2. int main(int argc, char *argv[])
    3. {
    4. QApplication a(argc, argv);
    5. NUninstallDialog w;
    6. w.show();
    7. return a.exec();
    8. }

    改为

    1. #include "qtsingleapplication/qtsingleapplication.h"
    2. int main(int argc, char *argv[])
    3. {
    4. QtSingleApplication a(QLatin1String("UninstallId"),argc, argv);
    5. if(a.isRunning())
    6. {
    7. NMessageDialog dialog(QApplication::focusWidget());
    8. dialog.setText(false,QObject::tr("有相同Uninstall卸载程序正在运行,再次打开前请先关闭。"));
    9. dialog.exec();
    10. return 1;
    11. }
    12. NUninstallDialog w;
    13. w.show();
    14. return a.exec();
    15. }

    这样修改后,打开多少个程序,就会出现多少提示框,不会有程序在后台不出现的情况了。

  8. 不知道是不是我下载的版本问题,还是哪里配置不对,编译后会有几个问题。看了一下代码,一个是因为命名空间的关系,根据提示在qtlockedfile.cpp和qtlockedfile_win.cpp开头加入using namespace QtLP_Private;。另一个是因为分了两个文件夹后的路径问题,在qtlocalpeer.cpp中,将#include "qtlockedfile.cpp"和#include "qtlockedfile_win.cpp"改为#include "../qtlockedfile/qtlockedfile.h"和#include "../qtlockedfile/qtlockedfile_win.cpp"(有需要也可以将_unix的也改一下)。

如果仅仅是解决打开多个程序,以上代码就能满足要求。但由于项目是需要同时检测安装包、卸载包、执行文件的,除了它们自己本身需要只允许一次以外,还需要这三个程序只能运行其中一个。

由于QtSingleApplication是继承QApplication的,而QT程序只允许有一个QApplication类。因此需要在QtSingleApplication中添加一个独立查询AppId的函数。

  1. 在QtSingleApplication中添加公有成员函数
    1. //QtSingleApplication.h
    2. bool isAppIdRuning(const QString &appId);
    1. //QtSingleApplication.cpp
    2. bool QtSingleApplication::isAppIdRuning(const QString &appId)
    3. {
    4. QtLocalPeer lpeer(this, appId);
    5. return lpeer.isClient();
    6. }

     

  2. 将main.cpp改为
    1. int main(int argc, char *argv[])
    2. {
    3. QtSingleApplication a(QLatin1String("UninstallId"),argc, argv);
    4. if(a.isRunning())
    5. {
    6. NMessageDialog dialog(QApplication::focusWidget());
    7. dialog.setText(false,QObject::tr("有相同Uninstall卸载程序正在运行,再次打开前请先关闭。"));
    8. dialog.exec();
    9. return 1;
    10. }
    11. if(a.isAppIdRuning("SetupId"))
    12. {
    13. NMessageDialog dialog(QApplication::focusWidget());
    14. dialog.setText(false,QObject::tr("Setup.exe安装程序正在运行,请关闭后再打开本卸载程序。"));
    15. dialog.exec();
    16. return 1;
    17. }
    18. if(a.isAppIdRuning("xxxId"))
    19. {
    20. NMessageDialog dialog(QApplication::focusWidget());
    21. dialog.setText(true,QObject::tr("xxx.exe运行中,是否强行关闭?"));
    22. if(dialog.exec() != QDialog::Accepted)
    23. {
    24. return 1;
    25. }
    26. }
    27. NUninstallDialog w;
    28. w.show();
    29. return a.exec();
    30. }

     

  3. 为了保证界面效果,语言翻译和皮肤的加载,要放到if(a.isRunning())前哦!

做安装包和卸载包其实还有几个问题没有攻克,只是这个刚好做起来有点麻烦,所以记录一下。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/118125
推荐阅读