239 lines
9.4 KiB
C++
239 lines
9.4 KiB
C++
#include <windows.h>
|
|
#include "client/windows/handler/exception_handler.h"
|
|
#include <global.h>
|
|
#include <QApplication>
|
|
#include <QSystemSemaphore>
|
|
#include <QSharedMemory>
|
|
#include <QMessageLogger>//日志
|
|
#include <QDebug>
|
|
#include <qmessagebox.h>
|
|
#include <qpushbutton.h>
|
|
#include <qlineedit.h>
|
|
#include <qlabel.h>
|
|
#include <qcombobox.h>
|
|
#include <QMetaType>
|
|
|
|
#include <appCore.hpp>
|
|
#include <QGuiApplication>
|
|
#include <windows.h> // GetModuleFileName, ShellExecuteEx, SW_NORMAL 等
|
|
#include <tchar.h> // TCHAR 相关操作
|
|
#include <shellapi.h> // SHELLEXECUTEINFO 结构体
|
|
#include <iostream> // std::cout (如果需要打印信息)
|
|
#include <tlhelp32.h> // CreateToolhelp32Snapshot, Process32First, Process32Next
|
|
#include <filesystem> // std::filesystem::path
|
|
|
|
#include <GUI/mainwindow.h>
|
|
|
|
#pragma region 程序启动功能
|
|
// 获取当前exe文件名
|
|
std::string getCurrentExeName() {
|
|
char exePath[MAX_PATH];
|
|
GetModuleFileNameA(NULL, exePath, MAX_PATH);
|
|
std::filesystem::path path(exePath);
|
|
return path.filename().string();
|
|
}
|
|
|
|
// 枚举窗口回调函数,用于置顶指定进程的窗口
|
|
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
|
|
DWORD* targetPid = (DWORD*)lParam;
|
|
DWORD windowPid;
|
|
GetWindowThreadProcessId(hwnd, &windowPid);
|
|
|
|
if (windowPid == *targetPid && IsWindowVisible(hwnd)) {
|
|
// 将窗口置顶并激活
|
|
SetForegroundWindow(hwnd);
|
|
ShowWindow(hwnd, SW_RESTORE);
|
|
return FALSE; // 停止枚举
|
|
}
|
|
return TRUE; // 继续枚举
|
|
}
|
|
|
|
// 检查应用是否已在运行,如果是则置顶
|
|
bool appIsRuning(){
|
|
std::string currentExeName = getCurrentExeName();
|
|
DWORD currentPid = GetCurrentProcessId();
|
|
|
|
// 创建进程快照
|
|
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
if (hSnapshot == INVALID_HANDLE_VALUE) {
|
|
return true; // 如果无法创建快照,允许启动
|
|
}
|
|
|
|
PROCESSENTRY32 pe32;
|
|
pe32.dwSize = sizeof(PROCESSENTRY32);
|
|
|
|
bool foundOtherInstance = false;
|
|
DWORD otherInstancePid = 0;
|
|
|
|
// 遍历进程
|
|
if (Process32First(hSnapshot, &pe32)) {
|
|
do {
|
|
// 比较进程名(忽略大小写)
|
|
if (_stricmp(pe32.szExeFile, currentExeName.c_str()) == 0 &&
|
|
pe32.th32ProcessID != currentPid) {
|
|
foundOtherInstance = true;
|
|
otherInstancePid = pe32.th32ProcessID;
|
|
break;
|
|
}
|
|
} while (Process32Next(hSnapshot, &pe32));
|
|
}
|
|
|
|
CloseHandle(hSnapshot);
|
|
|
|
if (foundOtherInstance) {
|
|
// 找到其他实例,将其置顶
|
|
EnumWindows(EnumWindowsProc, (LPARAM)&otherInstancePid);
|
|
return false; // 返回false表示已有实例在运行
|
|
}
|
|
|
|
return true; // 没有其他实例在运行
|
|
}
|
|
#pragma endregion
|
|
static bool dumpCallback(const wchar_t* dump_path,
|
|
const wchar_t* minidump_id,
|
|
void* context,
|
|
EXCEPTION_POINTERS* exinfo,
|
|
MDRawAssertionInfo* assertion,
|
|
bool succeeded) {
|
|
wprintf(L"Dump created at %s\\%s.dmp\n", dump_path, minidump_id);
|
|
return succeeded;
|
|
}
|
|
bool checkResourceExists(const QString& resourcePath) {
|
|
if (QFile::exists(resourcePath)) {
|
|
qDebug() << "文件存在:" << resourcePath;
|
|
return true;
|
|
}
|
|
else {
|
|
qDebug() << "文件不存在:" << resourcePath;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void connectSignalAndSlot(appCore* _core, MainWindow* _MainWindow, qtFuncBridge* bridge) {
|
|
QObject::connect(_core->_logService->getLogWidget(), &logToQtWidget::stdLogSignal,
|
|
_MainWindow->_logWidget, &logWidget::recvStdLogMsg);
|
|
QObject::connect(_core->_logService->getLogWidget(), &logToQtWidget::qtLogSignal,
|
|
_MainWindow->_logWidget, &logWidget::recvQtLogMsg);
|
|
QObject::connect(_core->_logService->getLogWidget(), &logToQtWidget::mainWindowStdLogSignal,
|
|
_MainWindow->_displayWidget, &displayWidget::recvMainWindowStdLogMsg);
|
|
QObject::connect(_core->_logService->getLogWidget(), &logToQtWidget::loadingWindow_appendConsoleLog,
|
|
_MainWindow, [=](const QString& text) {_MainWindow->_loadingWidget.appendConsoleLog(text); });
|
|
//BackEnd To Front
|
|
//等待界面
|
|
QObject::connect(bridge, &qtFuncBridge::loadingWindow_appendInitLog,
|
|
_MainWindow, [=](const QString& text, const QColor& color) {_MainWindow->_loadingWidget.appendInitLog(text, color); });
|
|
QObject::connect(bridge, &qtFuncBridge::loadingWindow_modifyLog,
|
|
_MainWindow, [=](int col, const QString& text, const QColor& color) {_MainWindow->_loadingWidget.modifyLog(col, text, color); });
|
|
QObject::connect(bridge, &qtFuncBridge::loadingWindow_clearLog,
|
|
_MainWindow, [=]() {_MainWindow->_loadingWidget.clearLog(); });
|
|
QObject::connect(bridge, &qtFuncBridge::pieWidgetAddNG,
|
|
_MainWindow, [=]() {_MainWindow->_displayWidget->_dsStatsWidget->addNg(); });
|
|
QObject::connect(bridge, &qtFuncBridge::pieWidgetAddOK,
|
|
_MainWindow, [=]() {_MainWindow->_displayWidget->_dsStatsWidget->addOK(); });
|
|
QObject::connect(bridge, &qtFuncBridge::histogramWidgetAddData,
|
|
_MainWindow, [=](std::vector<std::string>defects)
|
|
{_MainWindow->_displayWidget->_dayNightShiftHistogramWidget->addDefect(defects); });
|
|
QObject::connect(bridge, &qtFuncBridge::setPlcConnectionError,
|
|
_MainWindow, [=]() {_MainWindow->_displayWidget->_toolBarWidget->_ConnectionWidget->setPlcDisconnected(); });
|
|
QObject::connect(bridge, &qtFuncBridge::setPlcConnectionOk,
|
|
_MainWindow, [=]() {_MainWindow->_displayWidget->_toolBarWidget->_ConnectionWidget->setPlcConnected(); });
|
|
QObject::connect(bridge, &qtFuncBridge::setCamConnectionError,
|
|
_MainWindow, [=]() {_MainWindow->_displayWidget->_toolBarWidget->_ConnectionWidget->setCamDisconnected(); });
|
|
QObject::connect(bridge, &qtFuncBridge::setCamConnectionOk,
|
|
_MainWindow, [=]() {_MainWindow->_displayWidget->_toolBarWidget->_ConnectionWidget->setCamConnected(); });
|
|
//登录界面
|
|
QObject::connect(bridge, &qtFuncBridge::initResult,
|
|
_MainWindow, &MainWindow::recvInitFinished);
|
|
QObject::connect(bridge, &qtFuncBridge::initResult,
|
|
_core, &appCore::recvInitFinished);
|
|
//展示界面//主界面
|
|
QObject::connect(bridge, &qtFuncBridge::displayWidget_sendImg,
|
|
_MainWindow, &MainWindow::recvPixmapImageWidget);
|
|
|
|
//波形图
|
|
QObject::connect(bridge, &qtFuncBridge::summaryData_addData,
|
|
_MainWindow, &MainWindow::slot_summaryData_addData);
|
|
|
|
//排障
|
|
QObject::connect(bridge, &qtFuncBridge::runCommand_addBtn,
|
|
_MainWindow->_displayWidget->_runCommandWidget, &runCommandWidget::addBtn);
|
|
QObject::connect(_MainWindow->_displayWidget->_runCommandWidget,
|
|
&runCommandWidget::excuteCommandPreset,
|
|
[=](QString uuid) {_core->_backEnd.backend->excuteCliCommandPreset(uuid); });
|
|
QObject::connect(bridge, &qtFuncBridge::runCommand_addPlcValueViewer,
|
|
_MainWindow->_displayWidget->_runCommandWidget, &runCommandWidget::addPlcValueViewer);
|
|
QObject::connect(bridge, &qtFuncBridge::runCommand_refeshPlcValueViewer,
|
|
_MainWindow->_displayWidget->_runCommandWidget, &runCommandWidget::refreshPlcValueViewer);
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
//if (!isRunAsAdmin())
|
|
//{
|
|
// restartAsAdmin();
|
|
// exit(0);
|
|
//}
|
|
|
|
#pragma region 设置显示控制栏
|
|
HWND hWnd = GetConsoleWindow();
|
|
ShowWindow(hWnd, SW_SHOW);
|
|
#pragma endregion
|
|
#pragma region 启动breakPad崩溃捕获
|
|
std::wstring dumpPath = L"./dumps";
|
|
CreateDirectoryW(dumpPath.c_str(), nullptr);
|
|
|
|
// 初始化 breakpad
|
|
google_breakpad::ExceptionHandler eh(
|
|
dumpPath,
|
|
/*FilterCallback*/ nullptr,
|
|
dumpCallback,
|
|
/*context*/ nullptr,
|
|
/*install_handler*/ true
|
|
);
|
|
#pragma endregion
|
|
|
|
appCore _core;
|
|
auto& config = appConfig::getInstance();
|
|
config.consoleHandle = hWnd;
|
|
qtFuncBridge bridge; // 创建 C++ 对象
|
|
//检测是否已运行
|
|
if (appIsRuning() == false)
|
|
exit(0);
|
|
//////////
|
|
#pragma region 注册信号槽变量
|
|
qRegisterMetaType<cv::Mat*>("matPtr");
|
|
qRegisterMetaType<std::string>("stdString");
|
|
qRegisterMetaType<historyPack>("historyPack");
|
|
qRegisterMetaType<Qt::GlobalColor>("QtGlobalColor");
|
|
|
|
qRegisterMetaType<showImgPack>("showImgPack");
|
|
qRegisterMetaType<initStatus>("initStatus");
|
|
qRegisterMetaType<cv::Mat>("mat");
|
|
qRegisterMetaType<std::vector<std::string>>("vectorstring");
|
|
qRegisterMetaType<std::vector<std::pair<QString, int>>>("constvpqi");
|
|
|
|
#pragma endregion
|
|
QApplication a(argc, argv);
|
|
_core.initDatabase(); // 初始化数据库
|
|
QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + "/sqldrivers");
|
|
QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath());
|
|
MainWindow w(&config,&bridge, config.settingJson);
|
|
connectSignalAndSlot(&_core, &w, &bridge); // 连接信号和槽
|
|
w.show();
|
|
QThread::msleep(100);
|
|
// 创建后端对象
|
|
_core._backEnd.loadCore(config.dataBase,&bridge, config.settingJson["backend"]); // 加载核心功能
|
|
#if HIDE_CONSOLE
|
|
if (config.consoleHandle) {
|
|
ShowWindow(config.consoleHandle, SW_HIDE);
|
|
_core._logService->disableConsoleOutput();
|
|
}// 隐藏控制台窗口
|
|
#endif
|
|
w.registerQuitFunc([&]() {
|
|
_core._backEnd.releaseCore(); // 释放核心功能
|
|
QThread::msleep(100);
|
|
if (config.dataBase) delete config.dataBase;
|
|
config.dataBase = nullptr;
|
|
});
|
|
return a.exec();
|
|
} |