processthread.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. #include "processthread.h"
  2. #include "api/configapi.h"
  3. #include "appevent.h"
  4. #include "processmodel.h"
  5. #include "qjsonarray.h"
  6. #include "qjsonobject.h"
  7. #include <cwf/sqldatabasestorage.h>
  8. #include <optional>
  9. #include "api/processapi.h"
  10. #include "qjsonvalue.h"
  11. #include "qlist.h"
  12. #include "qmessagebox.h"
  13. #include "qnamespace.h"
  14. #include "basemainTr.h"
  15. CWF::SqlDatabaseStorage storage("QSQLITE", "localhost", "postgres", "postgres", "1234", 5432);
  16. // 将 FILETIME 转换为 Unix 时间戳
  17. static qint64 fileTimeToUnixTimestamp(FILETIME ft)
  18. {
  19. // FILETIME 是自 1601 年以来的 100 毫微秒数
  20. ULARGE_INTEGER ull;
  21. ull.LowPart = ft.dwLowDateTime;
  22. ull.HighPart = ft.dwHighDateTime;
  23. // FILETIME 和 时间戳的 基础时间不一样
  24. // 转换为秒,并减去 1601 到 1970 年之间的秒数
  25. if (ull.QuadPart / 10000000LL > 11644473600LL) {
  26. qint64 timestamp = ull.QuadPart / 10000000LL - 11644473600LL;
  27. return timestamp;
  28. }
  29. return ull.QuadPart / 10000000LL;
  30. }
  31. QString convertSecondsToTimeFormat(int totalSeconds)
  32. {
  33. int days = totalSeconds / (24 * 3600); // 计算天数
  34. int hours = (totalSeconds % (24 * 3600)) / 3600; // 计算小时
  35. int minutes = (totalSeconds % 3600) / 60; // 计算分钟
  36. int seconds = totalSeconds % 60; // 计算秒数
  37. // 返回格式化后的字符串,并使用 tr() 标记可翻译的文本
  38. return QString(Tr::tr("%1days%2hours%3minutes%4seconds"))
  39. .arg(days)
  40. .arg(hours)
  41. .arg(minutes)
  42. .arg(seconds);
  43. }
  44. ///
  45. /// \brief 转换到分钟
  46. /// \param totalSeconds
  47. /// \return
  48. ///
  49. QString convertSecondsToMinutesTimeFormat(int totalSeconds)
  50. {
  51. // 只计算分钟
  52. int minutes = totalSeconds / 60;
  53. return QString::number(minutes);
  54. }
  55. void ProcessThread::sendExitTime(qint64 updataTime)
  56. {
  57. TC::ProcessNameApi processNameApi;
  58. QJsonArray serverArray = processNameApi.get();
  59. // 获取过滤名单
  60. QSet<QString> filter;
  61. for (const QJsonValue &item : serverArray) {
  62. if (!item.isObject()) {
  63. return;
  64. }
  65. const QJsonObject object = item.toObject();
  66. const QString name = object["name"].toString();
  67. if (object.contains("is_confirmed")) {
  68. if (object["is_confirmed"].toInt() == 2) {
  69. filter.insert(name);
  70. }
  71. }
  72. }
  73. ProcessModel processModel{storage};
  74. // 在数据库 获取 不是这个更新日期的数据
  75. CWF::SqlQueryManager qry(storage);
  76. qry.select("*", processModel.getTableName())
  77. .where(QString("updataTime != '%1' OR updataTime IS NULL").arg(updataTime));
  78. qry.prepare();
  79. QJsonObject jsonObject = qry.exec();
  80. QJsonArray jsonArray = qry.toJson();
  81. QJsonArray sendJsonArray;
  82. if (jsonArray.size() > 0) {
  83. for (const auto &json : jsonArray) {
  84. const QJsonObject object = json.toObject();
  85. const QString name = object["processName"].toString();
  86. QJsonObject sendObject;
  87. sendObject.insert("pid", object["pid"]);
  88. sendObject.insert("pid_name", object["processName"]);
  89. sendObject.insert("begin_time", object["creationTime"]);
  90. sendObject.insert("end_time", object["exitTime"]);
  91. sendObject.insert("last_check_time", object["updataTime"]);
  92. sendObject.insert("status", 1);
  93. sendObject.insert("notes", "");
  94. // 存在过滤里面的 不发送数据
  95. if (!filter.contains(name)) {
  96. sendJsonArray.append(sendObject);
  97. }
  98. }
  99. }
  100. // 上传 后 删除
  101. if (sendJsonArray.size() > 0) {
  102. TC::ProcessApi processApi(sendJsonArray);
  103. bool isSendok = processApi.post();
  104. if (isSendok) {
  105. // 移除发送到服务器的本地数据
  106. CWF::SqlQueryManager qry(storage);
  107. qry.remove(processModel.getTableName(),
  108. QString("updataTime != '%1' OR updataTime IS NULL").arg(updataTime));
  109. qry.prepare();
  110. QJsonObject jsonObject = qry.exec();
  111. QJsonArray jsonArray = qry.toJson();
  112. }
  113. }
  114. QVariant messageBoxPointX = QVariant();
  115. QVariant messageBoxPointY = QVariant();
  116. QVariant messageText = QVariant("");
  117. QVariant messageTitle = QVariant(Tr::tr("Tips"));
  118. {
  119. TC::ConfigApi configApi("messageBoxPointX");
  120. std::optional<QVariant> value = configApi.get();
  121. if (value.has_value()) {
  122. messageBoxPointX = value.value();
  123. }
  124. }
  125. {
  126. TC::ConfigApi configApi("messageBoxPointY");
  127. std::optional<QVariant> value = configApi.get();
  128. if (value.has_value()) {
  129. messageBoxPointY = value.value();
  130. }
  131. }
  132. {
  133. TC::ConfigApi configApi("messageText");
  134. std::optional<QVariant> value = configApi.get();
  135. if (value.has_value()) {
  136. messageText = value.value();
  137. }
  138. }
  139. {
  140. TC::ConfigApi configApi("messageTitle");
  141. std::optional<QVariant> value = configApi.get();
  142. if (value.has_value()) {
  143. messageTitle = value.value();
  144. }
  145. }
  146. for (const QJsonValue &item : serverArray) {
  147. if (!item.isObject()) {
  148. return;
  149. }
  150. const QJsonObject object = item.toObject();
  151. const QString name = object["name"].toString();
  152. const QString zhName = object["chinese_name"].toString();
  153. if (object.contains("is_prompt")) {
  154. if (object["is_prompt"].toInt() == 2) {
  155. const QString name = object["name"].toString();
  156. const QString zhName = object["chinese_name"].toString();
  157. const int time = object["prompt_time"].toInt();
  158. if (time > 0) {
  159. const QString whereTime = QString("(updataTime - lastAlertTime) > %1").arg(time);
  160. const QString whereProcessName = QString("processName = '%1'").arg(name);
  161. const QString whereUpdataTime = QString("updataTime = '%1'").arg(updataTime);
  162. CWF::SqlQueryManager qry(storage);
  163. qry.select("*", processModel.getTableName())
  164. .where(QString("%1 AND %2 AND %3")
  165. .arg(whereTime)
  166. .arg(whereProcessName)
  167. .arg(whereUpdataTime));
  168. qry.prepare();
  169. QJsonObject jsonObject = qry.exec();
  170. QJsonArray jsonArray = qry.toJson();
  171. qDebug() << jsonArray;
  172. for (const auto &value : jsonArray) {
  173. const QJsonObject object = value.toObject();
  174. const QString processName = object["processName"].toString();
  175. const qint64 runTime = object["exitTime"].toVariant().toLongLong()
  176. - object["creationTime"].toVariant().toLongLong();
  177. const QString text = QString(
  178. tr("Program %1 has been used for %2 minutes%3")
  179. .arg(zhName)
  180. .arg(convertSecondsToMinutesTimeFormat(runTime))
  181. .arg(messageText.toString()));
  182. emit messageBox(text, messageBoxPointX, messageBoxPointY, messageTitle);
  183. // 更新 lastAlertTime
  184. ProcessModel processModel{storage};
  185. processModel.buildFromJson(object);
  186. // 更新 消息时间
  187. processModel.setLastAlertTime(updataTime);
  188. processModel.save();
  189. }
  190. }
  191. }
  192. }
  193. }
  194. // for (const QJsonValue &item : array) {
  195. // if (item.isObject()) {
  196. // const QJsonObject object = item.toObject();
  197. // const QString name = object["name"].toString();
  198. // const QString zhName = object["chinese_name"].toString();
  199. // if (object.contains("is_prompt")) {
  200. // if (object["is_prompt"].toInt() == 2) {
  201. // messageProcessName[name] = zhName;
  202. // };
  203. // }
  204. // }
  205. // }
  206. // qDebug() << messageProcessName;
  207. // // SELECT * FROM ProcessTime WHERE (updataTime - lastAlertTime) > 1565;
  208. // if (time > 0) {
  209. // const QString whereTime = QString("(updataTime - lastAlertTime) > %1").arg(time);
  210. // const QString whereProcessName = QString("processName = '%1'").arg("WeChat.exe");
  211. // CWF::SqlQueryManager qry(storage);
  212. // qry.select("*", processModel.getTableName()).where(whereTime);
  213. // qry.prepare();
  214. // QJsonObject jsonObject = qry.exec();
  215. // QJsonArray jsonArray = qry.toJson();
  216. // const QStringList keys = messageProcessName.keys();
  217. // for (const auto &value : jsonArray) {
  218. // // SLDWORKS.exe
  219. // const QJsonObject object = value.toObject();
  220. // const QString processName = object["processName"].toString();
  221. // const qint64 runTime = object["exitTime"].toVariant().toLongLong()
  222. // - object["creationTime"].toVariant().toLongLong();
  223. // for (const QString &key : keys) {
  224. // if (processName.compare(key, Qt::CaseSensitivity::CaseInsensitive) == 0) {
  225. // const QString text = QString(tr("Program %1 has been used for %2 minutes%3")
  226. // .arg(messageProcessName[key])
  227. // .arg(convertSecondsToMinutesTimeFormat(runTime))
  228. // .arg(messageText.toString()));
  229. // emit messageBox(text, messageBoxPointX, messageBoxPointY, messageTitle);
  230. // }
  231. // }
  232. // // 更新 lastAlertTime
  233. // ProcessModel processModel{storage};
  234. // processModel.buildFromJson(object);
  235. // // 更新 消息时间
  236. // processModel.setLastAlertTime(updataTime);
  237. // processModel.save();
  238. // }
  239. // }
  240. }
  241. bool ProcessThread::upDataProcessSql()
  242. {
  243. std::vector<std::shared_ptr<ProcessMonitor::ProcessInfo>> timeProcessVector
  244. = processMonitor.checkProcesses();
  245. // 退出时间默认当前时间 然后更新
  246. auto exitTimestamp = QDateTime::currentSecsSinceEpoch();
  247. auto updataTimestamp = QDateTime::currentSecsSinceEpoch();
  248. QStringList sqlValues;
  249. for (auto timeProcess : timeProcessVector) {
  250. qint64 timestamp = fileTimeToUnixTimestamp(timeProcess->creationTime);
  251. ProcessModel processModel{storage};
  252. CWF::SqlQueryManager qry(storage);
  253. qry.select("*", processModel.getTableName())
  254. .where(QString("pid == '%1' AND processName == '%2'")
  255. .arg(timeProcess->pid)
  256. .arg(timeProcess->processName.c_str()));
  257. qry.prepare();
  258. QJsonObject jsonObject = qry.exec();
  259. if (jsonObject["success"].toBool()) {
  260. // 查询或者替换 ?
  261. QJsonArray array = qry.toJson();
  262. if (array.size() > 0) {
  263. // 替换
  264. for (const QJsonValue &info : array) {
  265. const QJsonObject object = info.toObject();
  266. //数据还原到 结构体
  267. processModel.buildFromJson(object);
  268. // 更新 结束时间
  269. processModel.setExitTime(exitTimestamp);
  270. processModel.setUpdataTime(updataTimestamp);
  271. processModel.save();
  272. }
  273. } else {
  274. // 插入数据
  275. processModel.setProcessName(timeProcess->processName.c_str());
  276. processModel.setPid(timeProcess->pid);
  277. processModel.setCreationTime(timestamp);
  278. processModel.setExitTime(exitTimestamp);
  279. processModel.setUpdataTime(updataTimestamp);
  280. processModel.setLastAlertTime(updataTimestamp);
  281. processModel.save();
  282. }
  283. }
  284. // qDebug().noquote().nospace() << jsonObject << qry.toJson();
  285. // jsonObject.insert("begin_time", object["creationTime"]);
  286. // jsonObject.insert("end_time", object["exitTime"]);
  287. // jsonObject.insert("last_check_time", object["updataTime"]);
  288. // jsonObject.insert("status", 1);
  289. // jsonObject.insert("notes", "");
  290. // FILETIME ft = timeProcess->creationTime;
  291. // FILETIME currentTime;
  292. // GetSystemTimeAsFileTime(&currentTime);
  293. // ULARGE_INTEGER creation, current;
  294. // creation.LowPart = ft.dwLowDateTime;
  295. // creation.HighPart = ft.dwHighDateTime;
  296. // current.LowPart = currentTime.dwLowDateTime;
  297. // current.HighPart = currentTime.dwHighDateTime;
  298. // ULONGLONG elapsedSeconds = (current.QuadPart - creation.QuadPart) / 10000000;
  299. // // 计算天、小时、分钟和秒
  300. // ULONGLONG days = elapsedSeconds / 86400; // 1天 = 86400秒
  301. // ULONGLONG hours = (elapsedSeconds % 86400) / 3600; // 1小时 = 3600秒
  302. // ULONGLONG minutes = (elapsedSeconds % 3600) / 60; // 1分钟 = 60秒
  303. // ULONGLONG seconds = elapsedSeconds % 60; // 剩余秒数
  304. // // 打印进程的运行时间
  305. // qDebug() << QString::fromStdString(timeProcess->processName) //
  306. // << days << hours << minutes << seconds << timestamp;
  307. /*
  308. INSERT OR REPLACE INTO ProcessTime (pid, processName, creationTime, exitTime)
  309. VALUES
  310. (123, 'process1', strftime('%s', 'now'), strftime('%s', 'now')),
  311. (124, 'process2', strftime('%s', 'now'), strftime('%s', 'now')),
  312. (125, 'process3', strftime('%s', 'now'), strftime('%s', 'now'));
  313. */
  314. // sqlValues.append(QString("(%1,'%2',%3,%4,%5)")
  315. // .arg(timeProcess->pid) // pid
  316. // .arg(timeProcess->processName.c_str()) // 进程名
  317. // .arg(timestamp) // 开始时间戳
  318. // .arg(exitTimestamp) // 结束时间戳
  319. // .arg(updataTimestamp)); // 数据更新时间
  320. }
  321. // const QString query = QString(
  322. // R"(INSERT OR REPLACE INTO ProcessTime
  323. // (pid, processName, creationTime, exitTime, updataTime)
  324. // VALUES
  325. // %1)")
  326. // .arg(sqlValues.join(","));
  327. // // 使用上述插入或者替换
  328. // // 首先查找
  329. // QString where;
  330. // CWF::SqlQueryManager qry(storage);
  331. // QJsonObject jsonObject = qry.exec(query);
  332. // 发送更新后的数据
  333. sendExitTime(updataTimestamp);
  334. // if (jsonObject.contains("success")) {
  335. // if (jsonObject["success"].toBool()) {
  336. // return true;
  337. // }
  338. // }
  339. return false;
  340. }
  341. ProcessThread::ProcessThread(
  342. QObject *parent)
  343. : QThread{parent}
  344. {}
  345. void ProcessThread::run()
  346. {
  347. ProcessModel processModel{storage};
  348. processModel.updateDB();
  349. {
  350. const QString query = QString("CREATE UNIQUE INDEX %2_%3_unique ON %1 (%2, %3);")
  351. .arg(processModel.getTableName())
  352. .arg("pid")
  353. .arg("processName");
  354. CWF::SqlQuery qry(storage);
  355. qry.exec(query);
  356. }
  357. QElapsedTimer timer; // 创建高精度计时器
  358. timer.start(); // 启动计时器
  359. upDataProcessSql();
  360. while (true) {
  361. // 校验网络
  362. if (timer.elapsed() >= 30 * 1000) { // 检查是否经过1分钟
  363. timer.restart(); // 重新启动计时器
  364. upDataProcessSql();
  365. }
  366. msleep(1000); // 休息1秒
  367. }
  368. }