#include "processthread.h" #include "api/configapi.h" #include "appevent.h" #include "processmodel.h" #include "qjsonarray.h" #include "qjsonobject.h" #include #include #include "api/processapi.h" #include "qjsonvalue.h" #include "qlist.h" #include "qmessagebox.h" #include "qnamespace.h" #include "basemainTr.h" CWF::SqlDatabaseStorage storage("QSQLITE", "localhost", "postgres", "postgres", "1234", 5432); // 将 FILETIME 转换为 Unix 时间戳 static qint64 fileTimeToUnixTimestamp(FILETIME ft) { // FILETIME 是自 1601 年以来的 100 毫微秒数 ULARGE_INTEGER ull; ull.LowPart = ft.dwLowDateTime; ull.HighPart = ft.dwHighDateTime; // FILETIME 和 时间戳的 基础时间不一样 // 转换为秒,并减去 1601 到 1970 年之间的秒数 if (ull.QuadPart / 10000000LL > 11644473600LL) { qint64 timestamp = ull.QuadPart / 10000000LL - 11644473600LL; return timestamp; } return ull.QuadPart / 10000000LL; } QString convertSecondsToTimeFormat(int totalSeconds) { int days = totalSeconds / (24 * 3600); // 计算天数 int hours = (totalSeconds % (24 * 3600)) / 3600; // 计算小时 int minutes = (totalSeconds % 3600) / 60; // 计算分钟 int seconds = totalSeconds % 60; // 计算秒数 // 返回格式化后的字符串,并使用 tr() 标记可翻译的文本 return QString(Tr::tr("%1days%2hours%3minutes%4seconds")) .arg(days) .arg(hours) .arg(minutes) .arg(seconds); } /// /// \brief 转换到分钟 /// \param totalSeconds /// \return /// QString convertSecondsToMinutesTimeFormat(int totalSeconds) { // 只计算分钟 int minutes = totalSeconds / 60; return QString::number(minutes); } void ProcessThread::sendExitTime(qint64 updataTime) { TC::ProcessNameApi processNameApi; QJsonArray serverArray = processNameApi.get(); // 获取过滤名单 QSet filter; for (const QJsonValue &item : serverArray) { if (!item.isObject()) { return; } const QJsonObject object = item.toObject(); const QString name = object["name"].toString(); if (object.contains("is_confirmed")) { if (object["is_confirmed"].toInt() == 2) { filter.insert(name); } } } ProcessModel processModel{storage}; // 在数据库 获取 不是这个更新日期的数据 CWF::SqlQueryManager qry(storage); qry.select("*", processModel.getTableName()) .where(QString("updataTime != '%1' OR updataTime IS NULL").arg(updataTime)); qry.prepare(); QJsonObject jsonObject = qry.exec(); QJsonArray jsonArray = qry.toJson(); QJsonArray sendJsonArray; if (jsonArray.size() > 0) { for (const auto &json : jsonArray) { const QJsonObject object = json.toObject(); const QString name = object["processName"].toString(); QJsonObject sendObject; sendObject.insert("pid", object["pid"]); sendObject.insert("pid_name", object["processName"]); sendObject.insert("begin_time", object["creationTime"]); sendObject.insert("end_time", object["exitTime"]); sendObject.insert("last_check_time", object["updataTime"]); sendObject.insert("status", 1); sendObject.insert("notes", ""); // 存在过滤里面的 不发送数据 if (!filter.contains(name)) { sendJsonArray.append(sendObject); } } } // 上传 后 删除 if (sendJsonArray.size() > 0) { TC::ProcessApi processApi(sendJsonArray); bool isSendok = processApi.post(); if (isSendok) { // 移除发送到服务器的本地数据 CWF::SqlQueryManager qry(storage); qry.remove(processModel.getTableName(), QString("updataTime != '%1' OR updataTime IS NULL").arg(updataTime)); qry.prepare(); QJsonObject jsonObject = qry.exec(); QJsonArray jsonArray = qry.toJson(); } } QVariant messageBoxPointX = QVariant(); QVariant messageBoxPointY = QVariant(); QVariant messageText = QVariant(""); QVariant messageTitle = QVariant(Tr::tr("Tips")); { TC::ConfigApi configApi("messageBoxPointX"); std::optional value = configApi.get(); if (value.has_value()) { messageBoxPointX = value.value(); } } { TC::ConfigApi configApi("messageBoxPointY"); std::optional value = configApi.get(); if (value.has_value()) { messageBoxPointY = value.value(); } } { TC::ConfigApi configApi("messageText"); std::optional value = configApi.get(); if (value.has_value()) { messageText = value.value(); } } { TC::ConfigApi configApi("messageTitle"); std::optional value = configApi.get(); if (value.has_value()) { messageTitle = value.value(); } } for (const QJsonValue &item : serverArray) { if (!item.isObject()) { return; } const QJsonObject object = item.toObject(); const QString name = object["name"].toString(); const QString zhName = object["chinese_name"].toString(); if (object.contains("is_prompt")) { if (object["is_prompt"].toInt() == 2) { const QString name = object["name"].toString(); const QString zhName = object["chinese_name"].toString(); const int time = object["prompt_time"].toInt(); if (time > 0) { const QString whereTime = QString("(updataTime - lastAlertTime) > %1").arg(time); const QString whereProcessName = QString("processName = '%1'").arg(name); const QString whereUpdataTime = QString("updataTime = '%1'").arg(updataTime); CWF::SqlQueryManager qry(storage); qry.select("*", processModel.getTableName()) .where(QString("%1 AND %2 AND %3") .arg(whereTime) .arg(whereProcessName) .arg(whereUpdataTime)); qry.prepare(); QJsonObject jsonObject = qry.exec(); QJsonArray jsonArray = qry.toJson(); qDebug() << jsonArray; for (const auto &value : jsonArray) { const QJsonObject object = value.toObject(); const QString processName = object["processName"].toString(); const qint64 runTime = object["exitTime"].toVariant().toLongLong() - object["creationTime"].toVariant().toLongLong(); const QString text = QString( tr("Program %1 has been used for %2 minutes%3") .arg(zhName) .arg(convertSecondsToMinutesTimeFormat(runTime)) .arg(messageText.toString())); emit messageBox(text, messageBoxPointX, messageBoxPointY, messageTitle); // 更新 lastAlertTime ProcessModel processModel{storage}; processModel.buildFromJson(object); // 更新 消息时间 processModel.setLastAlertTime(updataTime); processModel.save(); } } } } } // for (const QJsonValue &item : array) { // if (item.isObject()) { // const QJsonObject object = item.toObject(); // const QString name = object["name"].toString(); // const QString zhName = object["chinese_name"].toString(); // if (object.contains("is_prompt")) { // if (object["is_prompt"].toInt() == 2) { // messageProcessName[name] = zhName; // }; // } // } // } // qDebug() << messageProcessName; // // SELECT * FROM ProcessTime WHERE (updataTime - lastAlertTime) > 1565; // if (time > 0) { // const QString whereTime = QString("(updataTime - lastAlertTime) > %1").arg(time); // const QString whereProcessName = QString("processName = '%1'").arg("WeChat.exe"); // CWF::SqlQueryManager qry(storage); // qry.select("*", processModel.getTableName()).where(whereTime); // qry.prepare(); // QJsonObject jsonObject = qry.exec(); // QJsonArray jsonArray = qry.toJson(); // const QStringList keys = messageProcessName.keys(); // for (const auto &value : jsonArray) { // // SLDWORKS.exe // const QJsonObject object = value.toObject(); // const QString processName = object["processName"].toString(); // const qint64 runTime = object["exitTime"].toVariant().toLongLong() // - object["creationTime"].toVariant().toLongLong(); // for (const QString &key : keys) { // if (processName.compare(key, Qt::CaseSensitivity::CaseInsensitive) == 0) { // const QString text = QString(tr("Program %1 has been used for %2 minutes%3") // .arg(messageProcessName[key]) // .arg(convertSecondsToMinutesTimeFormat(runTime)) // .arg(messageText.toString())); // emit messageBox(text, messageBoxPointX, messageBoxPointY, messageTitle); // } // } // // 更新 lastAlertTime // ProcessModel processModel{storage}; // processModel.buildFromJson(object); // // 更新 消息时间 // processModel.setLastAlertTime(updataTime); // processModel.save(); // } // } } bool ProcessThread::upDataProcessSql() { std::vector> timeProcessVector = processMonitor.checkProcesses(); // 退出时间默认当前时间 然后更新 auto exitTimestamp = QDateTime::currentSecsSinceEpoch(); auto updataTimestamp = QDateTime::currentSecsSinceEpoch(); QStringList sqlValues; for (auto timeProcess : timeProcessVector) { qint64 timestamp = fileTimeToUnixTimestamp(timeProcess->creationTime); ProcessModel processModel{storage}; CWF::SqlQueryManager qry(storage); qry.select("*", processModel.getTableName()) .where(QString("pid == '%1' AND processName == '%2'") .arg(timeProcess->pid) .arg(timeProcess->processName.c_str())); qry.prepare(); QJsonObject jsonObject = qry.exec(); if (jsonObject["success"].toBool()) { // 查询或者替换 ? QJsonArray array = qry.toJson(); if (array.size() > 0) { // 替换 for (const QJsonValue &info : array) { const QJsonObject object = info.toObject(); //数据还原到 结构体 processModel.buildFromJson(object); // 更新 结束时间 processModel.setExitTime(exitTimestamp); processModel.setUpdataTime(updataTimestamp); processModel.save(); } } else { // 插入数据 processModel.setProcessName(timeProcess->processName.c_str()); processModel.setPid(timeProcess->pid); processModel.setCreationTime(timestamp); processModel.setExitTime(exitTimestamp); processModel.setUpdataTime(updataTimestamp); processModel.setLastAlertTime(updataTimestamp); processModel.save(); } } // qDebug().noquote().nospace() << jsonObject << qry.toJson(); // jsonObject.insert("begin_time", object["creationTime"]); // jsonObject.insert("end_time", object["exitTime"]); // jsonObject.insert("last_check_time", object["updataTime"]); // jsonObject.insert("status", 1); // jsonObject.insert("notes", ""); // FILETIME ft = timeProcess->creationTime; // FILETIME currentTime; // GetSystemTimeAsFileTime(¤tTime); // ULARGE_INTEGER creation, current; // creation.LowPart = ft.dwLowDateTime; // creation.HighPart = ft.dwHighDateTime; // current.LowPart = currentTime.dwLowDateTime; // current.HighPart = currentTime.dwHighDateTime; // ULONGLONG elapsedSeconds = (current.QuadPart - creation.QuadPart) / 10000000; // // 计算天、小时、分钟和秒 // ULONGLONG days = elapsedSeconds / 86400; // 1天 = 86400秒 // ULONGLONG hours = (elapsedSeconds % 86400) / 3600; // 1小时 = 3600秒 // ULONGLONG minutes = (elapsedSeconds % 3600) / 60; // 1分钟 = 60秒 // ULONGLONG seconds = elapsedSeconds % 60; // 剩余秒数 // // 打印进程的运行时间 // qDebug() << QString::fromStdString(timeProcess->processName) // // << days << hours << minutes << seconds << timestamp; /* INSERT OR REPLACE INTO ProcessTime (pid, processName, creationTime, exitTime) VALUES (123, 'process1', strftime('%s', 'now'), strftime('%s', 'now')), (124, 'process2', strftime('%s', 'now'), strftime('%s', 'now')), (125, 'process3', strftime('%s', 'now'), strftime('%s', 'now')); */ // sqlValues.append(QString("(%1,'%2',%3,%4,%5)") // .arg(timeProcess->pid) // pid // .arg(timeProcess->processName.c_str()) // 进程名 // .arg(timestamp) // 开始时间戳 // .arg(exitTimestamp) // 结束时间戳 // .arg(updataTimestamp)); // 数据更新时间 } // const QString query = QString( // R"(INSERT OR REPLACE INTO ProcessTime // (pid, processName, creationTime, exitTime, updataTime) // VALUES // %1)") // .arg(sqlValues.join(",")); // // 使用上述插入或者替换 // // 首先查找 // QString where; // CWF::SqlQueryManager qry(storage); // QJsonObject jsonObject = qry.exec(query); // 发送更新后的数据 sendExitTime(updataTimestamp); // if (jsonObject.contains("success")) { // if (jsonObject["success"].toBool()) { // return true; // } // } return false; } ProcessThread::ProcessThread( QObject *parent) : QThread{parent} {} void ProcessThread::run() { ProcessModel processModel{storage}; processModel.updateDB(); { const QString query = QString("CREATE UNIQUE INDEX %2_%3_unique ON %1 (%2, %3);") .arg(processModel.getTableName()) .arg("pid") .arg("processName"); CWF::SqlQuery qry(storage); qry.exec(query); } QElapsedTimer timer; // 创建高精度计时器 timer.start(); // 启动计时器 upDataProcessSql(); while (true) { // 校验网络 if (timer.elapsed() >= 30 * 1000) { // 检查是否经过1分钟 timer.restart(); // 重新启动计时器 upDataProcessSql(); } msleep(1000); // 休息1秒 } }