Skip to content

Qt只启动一个实例

Published: at 09:52 AM | 2 min read

要想实现这个需求,就涉及到进程间通信了,怎样让当前启动的程序知道在它之前有没有程序在运行。 其实实现方法还是蛮多的,简单介绍几种:

下面是第三种方案的实现代码:

#ifndef RUNGUARD_H
#define RUNGUARD_H

#include <QObject>
#include <QSharedMemory>
#include <QSystemSemaphore>


class RunGuard
{

public:
	RunGuard(const QString& key);
	~RunGuard();

	bool isAnotherRunning();
	bool tryToRun();
	void release();

private:
	const QString key;
	const QString memLockKey;
	const QString sharedmemKey;

	QSharedMemory sharedMem;
	QSystemSemaphore memLock;

	Q_DISABLE_COPY(RunGuard)
};


#endif // RUNGUARD_H
#include "RunGuard.h"

#include <QCryptographicHash>


namespace
{

	QString generateKeyHash(const QString& key, const QString& salt)
	{
		QByteArray data;

		data.append(key.toUtf8());
		data.append(salt.toUtf8());
		data = QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex();

		return data;
	}

}


RunGuard::RunGuard(const QString& key)
	: key(key)
	, memLockKey(generateKeyHash(key, "_memLockKey"))
	, sharedmemKey(generateKeyHash(key, "_sharedmemKey"))
	, sharedMem(sharedmemKey)
	, memLock(memLockKey, 1)
{
	memLock.acquire();
	{
		QSharedMemory fix(sharedmemKey);
		fix.attach();
	}
	memLock.release();
}

RunGuard::~RunGuard()
{
	release();
}

bool RunGuard::isAnotherRunning()
{
	if (sharedMem.isAttached())
		return false;

	memLock.acquire();
	const bool isRunning = sharedMem.attach();
	if (isRunning)
		sharedMem.detach();
	memLock.release();

	return isRunning;
}

bool RunGuard::tryToRun()
{
	if (isAnotherRunning())   // Extra check
		return false;

	memLock.acquire();
	const bool result = sharedMem.create(sizeof(quint64));
	memLock.release();
	if (!result)
	{
		release();
		return false;
	}

	return true;
}

void RunGuard::release()
{
	memLock.acquire();
	if (sharedMem.isAttached())
		sharedMem.detach();
	memLock.release();
}

用法:

	RunGuard guard("69619FA7-4944-4CCA-BF69-83323F34D32F");
	if (!guard.tryToRun()) {
		return 0;
	}

69619FA7-4944-4CCA-BF69-83323F34D32F使用工具生成的随机GUID,你可以填任意字符串