Browse Source

添加 多重互斥

zhuizhu 1 year ago
parent
commit
1c85a06b45
5 changed files with 175 additions and 5 deletions
  1. 3 3
      api/tapi.cpp
  2. 161 2
      main.cpp
  3. 2 0
      processthread.cpp
  4. 2 0
      qtsingleapplication/qtlocalpeer.cpp
  5. 7 0
      updaterthread.cpp

+ 3 - 3
api/tapi.cpp

@@ -72,7 +72,7 @@ void information(const QString &text, const QString &title = Tr::tr("information
         parentWidget = widgetList.first();
     }
     Q_UNUSED(parentWidget)
-    qDebug() << parentWidget << text;
+    qDebug() << parentWidget << text << title;
     // 获取当前活动窗口
     // QMessageBox::information(parentWidget, title, text);
 }
@@ -89,7 +89,7 @@ static bool InterceptorsResponse(QNetworkReply *reply, QJsonValue &data)
             return false;
         }
 #ifdef QT_DEBUG
-        qDebug() << QString::fromUtf8(jsonDoc.toJson());
+        //qDebug() << QString::fromUtf8(jsonDoc.toJson());
 #endif
         data = jsonDoc.object();
         // if (jsonDoc.isObject()) {
@@ -181,7 +181,7 @@ QNetworkReply *NetworkAccessManager::createRequest(Operation op,
 
     const QUrl &url = request.url();
     const QString urlPath = url.path();
-    qDebug() << url;
+    // qDebug() << url;
     //设置白名单
     if (urlPath.indexOf(RefreshToken().url) >= 0 || urlPath.indexOf(Login().url) >= 0) {
     } else {

+ 161 - 2
main.cpp

@@ -7,6 +7,7 @@
 #include <QLocale>
 #include <QProcess>
 #include <QSettings>
+#include <QStandardPaths>
 #include <QTranslator>
 
 #include "hostthread.h"
@@ -17,6 +18,37 @@
 #include "qtsingleapplication.h"
 #include "updaterthread.h"
 
+std::vector<unsigned long> GetProcessIDsByName(const std::wstring &processName)
+{
+    std::vector<unsigned long> pids;
+
+    // 创建进程快照
+    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+    if (hSnapshot == INVALID_HANDLE_VALUE) {
+        //std::cerr << "Failed to take snapshot of processes" << Qt::endl;
+        return pids;
+    }
+
+    // 设置进程信息结构体
+    PROCESSENTRY32 pe32;
+    pe32.dwSize = sizeof(PROCESSENTRY32);
+
+    // 获取第一个进程
+    if (Process32First(hSnapshot, &pe32)) {
+        do {
+            // 检查进程名是否匹配
+            if (processName == pe32.szExeFile) {
+                pids.push_back(pe32.th32ProcessID); // 存储匹配的进程ID
+            }
+        } while (Process32Next(hSnapshot, &pe32)); // 获取下一个进程
+    }
+
+    // 关闭快照句柄
+    CloseHandle(hSnapshot);
+
+    return pids;
+}
+
 void addToStartup()
 {
     QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run",
@@ -24,7 +56,98 @@ void addToStartup()
     QString appPath = QCoreApplication::applicationFilePath(); // 获取应用程序路径
     settings.setValue("BaseMainApp", appPath); // 将应用程序路径添加到注册表
 }
+void setAutoStart(bool enable)
+{
+    QString appPath = QDir::toNativeSeparators(QCoreApplication::applicationFilePath());
+    QString taskName = "YourAppName"; // 替换为你的应用程序名称
+
+    if (enable) {
+        QString tempPath = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
+        QString xmlFilePath = QDir::toNativeSeparators(tempPath + "/task.xml");
+
+        QFile xmlFile(xmlFilePath);
+        if (xmlFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+            QString xmlContent = QString(R"(<?xml version="1.0" encoding="UTF-16"?>
+<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
+  <RegistrationInfo>
+    <Description>Auto start task for %1</Description>
+  </RegistrationInfo>
+  <Triggers>
+    <LogonTrigger>
+      <Enabled>true</Enabled>
+      <Delay>PT10S</Delay>
+    </LogonTrigger>
+  </Triggers>
+  <Principals>
+    <Principal id="Author">
+      <GroupId>S-1-5-32-544</GroupId>
+      <RunLevel>HighestAvailable</RunLevel>
+    </Principal>
+  </Principals>
+  <Settings>
+    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
+    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
+    <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
+    <AllowHardTerminate>true</AllowHardTerminate>
+    <StartWhenAvailable>true</StartWhenAvailable>
+    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
+    <IdleSettings>
+      <StopOnIdleEnd>false</StopOnIdleEnd>
+      <RestartOnIdle>false</RestartOnIdle>
+    </IdleSettings>
+    <AllowStartOnDemand>true</AllowStartOnDemand>
+    <Enabled>true</Enabled>
+    <Hidden>false</Hidden>
+    <RunOnlyIfIdle>false</RunOnlyIfIdle>
+    <WakeToRun>false</WakeToRun>
+    <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
+    <Priority>7</Priority>
+  </Settings>
+  <Actions Context="Author">
+    <Exec>
+      <Command>%2</Command>
+    </Exec>
+  </Actions>
+</Task>)")
+                                     .arg(taskName, appPath);
+
+            // 将内容写入为 UTF-16LE 格式
+            QTextStream out(&xmlFile);
+            out.setCodec("UTF-16LE");
+            out.setGenerateByteOrderMark(true);
+            out << xmlContent;
+            xmlFile.close();
 
+            QStringList arguments;
+            arguments << "/c"
+                      << "schtasks"
+                      << "/create"
+                      << "/tn" << taskName << "/xml" << xmlFilePath << "/f";
+
+            qDebug() << "Executing command with arguments:" << arguments;
+
+            QProcess process;
+            process.start("cmd.exe", arguments);
+            process.waitForFinished();
+
+            QString error = QString::fromLocal8Bit(process.readAllStandardError());
+            QString output = QString::fromLocal8Bit(process.readAllStandardOutput());
+
+            if (!error.isEmpty()) {
+                qDebug() << "Error output:" << error;
+            }
+            if (!output.isEmpty()) {
+                qDebug() << "Standard output:" << output;
+            }
+
+            xmlFile.remove();
+        }
+    } else {
+        QStringList arguments;
+        arguments << "/c" << "schtasks" << "/delete" << "/tn" << taskName << "/f";
+        QProcess::execute("cmd.exe", arguments);
+    }
+}
 void redirectOutputToLogFile()
 {
     // 重定向 qDebug、qWarning 和 qCritical 的输出
@@ -32,6 +155,9 @@ void redirectOutputToLogFile()
                               const QMessageLogContext &context,
                               const QString &msg) { // 获取当前日期
         Q_UNUSED(context)
+        if (type == QtWarningMsg) {
+            return;
+        }
         QString dateString = QDate::currentDate().toString("yyyy-MM-dd");
 
         // 获取应用程序的日志文件路径
@@ -77,9 +203,16 @@ int main(int argc, char *argv[])
     QDir dir;
     dir.mkdir("log"); // 创建日志目录
     addToStartup();   // 开机启动
+#ifdef QT_DEBUG
+    setAutoStart(false);
+#else
+    setAutoStart(true);
+    redirectOutputToLogFile(); // 日志
+#endif
 
-    // redirectOutputToLogFile(); // 日志
-    a.setApplicationVersion("1.1.2");
+    a.setOrganizationName("BaseMainApp");
+    a.setApplicationName("BaseMain");
+    a.setApplicationVersion("1.1.4");
     a.setQuitOnLastWindowClosed(false);
 
     QCommandLineParser parser;
@@ -90,10 +223,36 @@ int main(int argc, char *argv[])
     parser.addOption(debugOption);
     parser.process(a);
 
+    qDebug() << QCoreApplication::organizationName() << QCoreApplication::applicationName()
+             << QCoreApplication::applicationFilePath();
+    QString appFilePath = QCoreApplication::applicationFilePath();
+    QString appName = QFileInfo(appFilePath).fileName();
+
+    qDebug() << "Application Path:" << appFilePath;
+    qDebug() << "Application Name:" << appName;
     if (a.isRunning()) {
         a.sendMessage("", 1000);
         return 0;
     }
+    // 多重判断 防止异常
+    HANDLE hMutex = CreateMutex(NULL, TRUE, L"Global\\Unique_BaseMainApp");
+    // 检查是否已经有实例在运行
+    if (hMutex == NULL || GetLastError() == ERROR_ALREADY_EXISTS) {
+        return 0; // 退出当前程序,避免多个实例运行
+    }
+    // 多重判断
+    auto pids = GetProcessIDsByName(appName.toStdWString().c_str());
+    if (pids.size() > 1) {
+        qDebug() << appName << " size:" << pids.size();
+    }
+
+    qSetMessagePattern("[%{time process}][%{line}]"
+                       "%{if-debug}D%{endif}"
+                       "%{if-info}I%{endif}"
+                       "%{if-warning}W%{endif}"
+                       "%{if-critical}C%{endif}"
+                       "%{if-fatal}F%{endif}:"
+                       "%{message}  %{file}");
 
     QTranslator translator;
     const QStringList uiLanguages = QLocale::system().uiLanguages();

+ 2 - 0
processthread.cpp

@@ -151,6 +151,7 @@ const QJsonArray processNameArray()
             // If the config is a single object, we can wrap it in an array
             serverArray.append(jsonDoc.object());
         }
+        qDebug() << "use Local config";
     } else {
         // 写入本地配置
         QSettings settings(QSettings::NativeFormat,
@@ -162,6 +163,7 @@ const QJsonArray processNameArray()
         settings.setValue("serverArray",
                           QString(QJsonDocument(serverArray).toJson(QJsonDocument::Compact)));
         settings.endGroup();
+        qDebug() << "use server config";
     }
 
     return serverArray;

+ 2 - 0
qtsingleapplication/qtlocalpeer.cpp

@@ -87,6 +87,8 @@ QtLocalPeer::QtLocalPeer(QObject *parent, const QString &appId)
                        + QLatin1String("-lockfile");
     lockFile.setFileName(lockName);
     lockFile.open(QIODevice::ReadWrite);
+
+    qDebug() << "-----------" << lockFile.fileName();
 }
 
 bool QtLocalPeer::isClient()

+ 7 - 0
updaterthread.cpp

@@ -29,6 +29,11 @@ bool isNetworkAvailable()
     return success && response == "OK";
 }
 
+bool updateServer()
+{
+    return true;
+}
+
 bool runUpdate()
 {
     const QString app_version = qApp->applicationVersion();
@@ -76,6 +81,7 @@ void UpdaterThread::run()
     if (isNetworkAvailable()) {
         if (runUpdate()) {
         }
+        updateServer();
     }
     QElapsedTimer timer; // 创建高精度计时器
     timer.start();       // 启动计时器
@@ -87,6 +93,7 @@ void UpdaterThread::run()
             if (isNetworkAvailable()) {
                 if (runUpdate()) {
                 }
+                updateServer();
             }
         }