Qt6 防止程序多重启动,并实现双击图标显示已运行的程序

网友投稿 654 2022-05-29

欢迎来到我的博客,希望这篇文章对你有所帮助,如果觉得不错,请搜藏哈。

1 需求背景

Qt6 防止程序多重启动,并实现双击图标显示已运行的程序

还是原来的网络关机助手项目“PowerControl”,目前他有了一个新的运行环境,就是在我们的某个带有电脑的显示设备上面,可以理解为带有触摸功能的一体机,本来原生设计是无法触发这个需求的,但是由于信号的干扰没有很好的解决,导致整个屏幕下沉,屏幕的四周没法触摸,这就导致了Windows无法关机,也无法打开系统托盘。所以,关机就需要使用我的关机助手的界面来关机。

但是我的程序图标点击默认是启动程序,而我的程序有没有限制,而且默认还是最小化的,点再多也没有用,指示多开 了一堆程序而已。

所以本次需要增加以下功能

程序启动只能有一个进程,不能多开

双击桌面图标,如果程序启动,则显示程序,如果没有,则创建程序。

2 解决方案

要实现上面的功能,我先想到的就是寻找进程,程序启动的时候看看有没有这个的东西,但是呢,有没有搞过,这都21世纪了,百度一下,发现一个有很多种方法大致有一下几种

参考链接,这里只做搬运 https://blog.csdn.net/robertkun/article/details/8518576#

2.1共享内存

据说这种方法在Linux系统下会有一个内存释放的问题,在某种情况下会引起程序的异常或崩溃

核心代码如下

// 确保只运行一次 QSystemSemaphore sema("JAMKey",1,QSystemSemaphore::Open); sema.acquire();// 在临界区操作共享内存 SharedMemory QSharedMemory mem("SystemObject");// 全局对象名 if (!mem.create(1))// 如果全局对象以存在则退出 { QMessageBox::information(0, MESSAGEBOXTXT,"An instance has already been running."); sema.release();// 如果是 Unix 系统,会自动释放。 return 0; } sema.release();// 临界区

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

2.2使用QLocalServer和QLocalSocker

这种也是我使用的版本,参考链接找不到,不过代码都是找搬过来的,连接:https://blog.csdn.net/sunflover454/article/details/50426639

头文件代码

#ifndef SINGLEAPPLICATION_H #define SINGLEAPPLICATION_H #include #include class QWidget; class QLocalServer; class SingleApplication : public QApplication { Q_OBJECT public: SingleApplication(int &argc,char **argv); bool isRuning(); QWidget *mainWindow; private slots: void newLocalConnectioin(); private: void initLocalConnection(); void newLocalServer(); bool bRunning; QLocalServer *localServer; QString serverName; }; #endif // SINGLEAPPLICATION_H

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

原文件代码

#include "singleapplication.h" #include #include #include #include #include SingleApplication::SingleApplication(int &argc, char **argv) :QApplication(argc,argv),bRunning(false),localServer(nullptr),mainWindow(nullptr) { serverName = QFileInfo(QCoreApplication::applicationFilePath()).fileName(); initLocalConnection(); } bool SingleApplication::isRuning() { return bRunning; } void SingleApplication::newLocalConnectioin() { QLocalSocket *socket = localServer->nextPendingConnection(); if(!socket) return; socket->waitForReadyRead(1000); QTextStream stream(socket); delete socket; if(mainWindow != NULL) { mainWindow->raise(); mainWindow->activateWindow(); mainWindow->setWindowState((mainWindow->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); mainWindow->show(); } } void SingleApplication::initLocalConnection() { bRunning = false; QLocalSocket socket; socket.connectToServer(serverName); if(socket.waitForConnected(500)) { bRunning = true; QTextStream stream(&socket); QStringList args = QCoreApplication::arguments(); if(args.count() > 1) stream << args.last(); else stream << QString(); stream.flush(); socket.waitForBytesWritten(); return; } newLocalServer(); } void SingleApplication::newLocalServer() { localServer = new QLocalServer(this); connect(localServer,SIGNAL(newConnection()),this,SLOT(newLocalConnectioin())); if(!localServer->listen(serverName)) { if(localServer->serverError() == QAbstractSocket::AddressInUseError) { QLocalServer::removeServer(serverName); localServer->listen(serverName); } } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

main 调用

#include "mainwindow.h" #include #include void autoStart() { QString appName = QApplication::applicationName(); QString appPath = QApplication::applicationFilePath(); appPath = appPath.replace("/","\\"); QSettings *reg=new QSettings("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",QSettings::NativeFormat); QString val = reg->value(appName).toString(); if(val != appPath) reg->setValue(appName,appPath); reg->deleteLater(); } //int main(int argc, char *argv[]) //{ // QApplication a(argc, argv); // autoStart(); // MainWindow w; w.show(); // return a.exec(); //} int main(int argc, char *argv[]) { SingleApplication a(argc, argv); if(!a.isRuning()) { autoStart(); MainWindow w; a.mainWindow = &w; // w.show(); return a.exec(); } return 0; }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

2.3使用官方的QSignalApplication

官方类,但是默认不在Qt中,需要自己下载安装:参考链接https://blog.csdn.net/bloke_come/article/details/106319236

Qt

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:PDF文档签名证书帮助您签署可信的电子合同
下一篇:云化环境搭建
相关文章