Qt6 防止程序多重启动,并实现双击图标显示已运行的程序
欢迎来到我的博客,希望这篇文章对你有所帮助,如果觉得不错,请点赞搜藏哈。
1 需求背景
还是原来的网络关机助手项目“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 <QApplication>
#include <QObject>
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 <QWidget>
#include <QtNetwork/QLocalSocket>
#include <QtNetwork/QLocalServer>
#include <QFileInfo>
#include <QLibrary>
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 <QApplication>
#include <singleapplication.h>
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
文章来源: dreamlife.blog.csdn.net,作者:DreamLife.,版权归原作者所有,如需转载,请联系作者。
原文链接:dreamlife.blog.csdn.net/article/details/115528103
- 点赞
- 收藏
- 关注作者
评论(0)