-
Notifications
You must be signed in to change notification settings - Fork 1
/
singleinstance.cpp
96 lines (86 loc) · 2.82 KB
/
singleinstance.cpp
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include "singleinstance.h"
#include "systemhelper.h"
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QCoreApplication>
#ifdef Q_OS_WIN
#include <windows.h>
#endif
#ifdef Q_OS_LINUX
#include <sys/types.h>
#include <signal.h>
#endif
SingleInstance::SingleInstance(const QString lockId, const QApplication& app)
{
#ifdef Q_OS_WIN
// Kill BatteryLine v1.x
HWND hWndLegacy = FindWindowW(L"Joveler_BatteryLine", 0);
if (hWndLegacy != NULL) // Running BatteryLine found? Terminate it.
SendMessageW(hWndLegacy, WM_CLOSE, 0, 0);
#endif
this->lockId = lockId;
this->lock = new QLockFile(lockId + ".lock");
if (lock->tryLock(100))
{ // Lock success, leave process info (Win - hWnd, Linux - pid)
QFile pidFile(lockId + ".pid");
if (pidFile.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream out(&pidFile);
out.setEncoding(QStringConverter::Utf8);
out << QCoreApplication::applicationPid();
pidFile.close();
}
else // failure
{ // Silently ignore this, it is not likely to happen.
// SystemHelper::SystemWarning("BatteryLine is runnable, but it cannot write process id.");
}
}
else
{ // Lock failure, another instance is running - so kill that instance and terminate
qint64 runningPid = 0;
QFile pidFile(lockId + ".pid");
if (pidFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream in(&pidFile);
in.setEncoding(QStringConverter::Utf8);
runningPid = in.readLine().trimmed().toInt();
pidFile.close();
}
else // failure
{
SystemHelper::SystemError("Another instance of BatteryLine is running.");
}
// Try to kill running instance and terminate
#ifdef Q_OS_WIN
DWORD winPid = static_cast<DWORD>(runningPid);
HWND hWndIter = FindWindowW(NULL, NULL); // Will iterate all 'hWnd'es to find BatteryLine
while (hWndIter != NULL)
{
DWORD getPid = 0;
GetWindowThreadProcessId(hWndIter, &getPid);
if (winPid == getPid && GetParent(hWndIter) == NULL) // Only check top-level window
{
SendMessageW(hWndIter, WM_CLOSE, 0, 0);
break;
}
hWndIter = GetWindow(hWndIter, GW_HWNDNEXT);
}
#elif defined(Q_OS_LINUX)
pid_t linuxPid = static_cast<pid_t>(runningPid);
kill(linuxPid, SIGTERM);
#endif
SystemHelper::QtExit(0);
}
connect(&app, &QCoreApplication::aboutToQuit, this, &SingleInstance::AboutToQuit);
}
SingleInstance::~SingleInstance()
{
delete lock;
}
void SingleInstance::AboutToQuit()
{
lock->unlock();
QFile::remove(lockId + ".lock");
QFile::remove(lockId + ".pid");
}