| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- #include <QApplication>
- #include <QCoreApplication>
- #include <QCommandLineParser>
- #include <QDebug>
- #include <QDir>
- #include <QLocale>
- #include <QProcess>
- #include <QSettings>
- #include <QStandardPaths>
- #include <QTranslator>
- #include "hostthread.h"
- #include "messagequeue.h"
- #include "processthread.h"
- #include "qdatetime.h"
- #include "qobject.h"
- #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",
- QSettings::NativeFormat);
- 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 的输出
- qInstallMessageHandler([](QtMsgType type,
- const QMessageLogContext &context,
- const QString &msg) { // 获取当前日期
- Q_UNUSED(context)
- if (type == QtWarningMsg) {
- return;
- }
- QString dateString = QDate::currentDate().toString("yyyy-MM-dd");
- // 获取应用程序的日志文件路径
- QString logFileName = "./log/" + dateString + "_base.txt";
- // 创建 QFile 对象
- QFile logFile(logFileName);
- // 打开文件进行写入,如果文件不存在则创建
- if (!logFile.open(QIODevice::Append | QIODevice::Text)) {
- qWarning() << "Unable to open log file for writing:" << logFile.errorString();
- return;
- }
- QTextStream out(&logFile);
- QString timeString = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
- switch (type) {
- case QtDebugMsg:
- out << timeString << " [DEBUG] " << msg << "\n";
- break;
- case QtWarningMsg:
- out << timeString << " [WARNING] " << msg << "\n";
- break;
- case QtCriticalMsg:
- out << timeString << " [CRITICAL] " << msg << "\n";
- break;
- case QtFatalMsg:
- out << timeString << " [FATAL] " << msg << "\n";
- // abort(); // 终止程序
- case QtInfoMsg:
- break;
- }
- logFile.close();
- });
- }
- int main(int argc, char *argv[])
- {
- // QApplication a(argc, argv);
- SharedTools::QtSingleApplication a("BaseMainApp", argc, argv);
- QDir dir;
- dir.mkdir("log"); // 创建日志目录
- addToStartup(); // 开机启动
- #ifdef QT_DEBUG
- setAutoStart(false);
- #else
- setAutoStart(true);
- redirectOutputToLogFile(); // 日志
- #endif
- a.setOrganizationName("BaseMainApp");
- a.setApplicationName("BaseMain");
- a.setApplicationVersion("1.1.4");
- a.setQuitOnLastWindowClosed(false);
- QCommandLineParser parser;
- parser.addHelpOption();
- parser.addVersionOption();
- QCommandLineOption debugOption("debug", "Enable debug mode");
- 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();
- for (const QString &locale : uiLanguages) {
- const QString baseName = "basemain_" + QLocale(locale).name();
- if (translator.load(":/i18n/" + baseName)) {
- a.installTranslator(&translator);
- break;
- }
- }
- HostThread host;
- UpdaterThread thread;
- ProcessThread Process;
- MessageQueue messageQueue;
- QObject::connect(&Process, &ProcessThread::messageBox, &messageQueue, &MessageQueue::addMessage);
- QObject::connect(&Process, &ProcessThread::finished, &Process, &QObject::deleteLater);
- thread.start();
- Process.start();
- host.start();
- return a.exec();
- }
|