HM-SPMS/product/src/tools/setup/setup_installer/SetupFuncWindows.cpp
2025-03-13 15:19:38 +08:00

372 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**********************************************************************************
* @file SetupFuncWindows.cpp
* @brief Windows系统设置函数
* @author yikenan
* @versiong 1.0
* @date
**********************************************************************************/
//< 仅在Win系统下编译
#ifdef OS_WINDOWS
#include <windows.h>
#include <tchar.h>
#include <QtCore>
#include "SetupFunc.h"
#include "setupCommon.h"
#include "setup/CommonDef.h"
namespace iot_sys
{
const static char* g_platform_dir_name = PLATFORM_DIR;
//< 注册系统服务,并设置自启动
bool regSysService(QString &strErr,QString path)
{
bool bRet = false;
const QString strExec = QDir::toNativeSeparators
(path + QString("/platform/%1/sys_launcher_srv.exe").arg(PLATFORM_DIR));
qDebug() << strExec;
//< 判断文件存在
if (!QFile::exists(strExec))
{
strErr = QObject::tr("文件不存在!") + "\n" + strExec;
return false;
}
//< 打开服务控制管理器
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == hSCM)
{
strErr = QObject::tr("打开服务管理器失败,请确认是否具有权限!");
}
else
{
//< 判断服务是否已存在
SC_HANDLE hService = ::OpenService(hSCM, g_pTCharLauncherServiceName, SERVICE_QUERY_CONFIG);
if (NULL == hService)
{
//< 创建服务
//< 使用SERVICE_USER_XXX_PROCESS服务类型用户登录时启动不影响共享内存等的使用
//< 若使用SERVICE_WIN32_XXX_PROCESS等服务类型程序以system用户启动共享内存被隔离其他用户访问不到
//< todo 最好是实时库等使用共享内存、互斥锁的程序修改声明方式为Global突破用户间的隔离原因
//< 1、如上面说的SERVICE_USER_XXX_PROCESS是用户登录时才启动服务自启的实际意义打折扣
//< 2、多用户登录时会启动多个实例而实际上由于端口占用等原因是起不来的
//< 3、本程序停止服务时存在困难见下面unregSysService()中的注释。
hService = ::CreateService(
hSCM, g_pTCharLauncherServiceName, g_pTCharLauncherServiceName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
strExec.toStdWString().c_str(), NULL, NULL, NULL, NULL, NULL);
if (hService == NULL)
{
strErr = QObject::tr("注册服务失败,请确认是否具有权限!");
}
else
{
SERVICE_DESCRIPTION stSrvDesc;
TCHAR szDesc[] = _T("监控系统加载服务");
stSrvDesc.lpDescription = szDesc;
if (::ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &stSrvDesc))
{
bRet = true;
}
::CloseServiceHandle(hService);
}
}
else
{
strErr = QObject::tr("已设置服务自启动,若需重新设置,请先取消!");
::CloseServiceHandle(hService);
}
::CloseServiceHandle(hSCM);
}
return bRet;
}
//----------------------------------------
//< 设置HMI自启动
bool setHmiAutoStart(QString &strErr,QString path)
{
const QString strExec =QDir::toNativeSeparators
(path + "/sys_startup.exe");
//< 判断文件存在
if (!QFile::exists(strExec))
{
strErr = QObject::tr("文件不存在!") + "\n" + strExec;
return false;
}
QSettings objRegSetting(g_pszAutoRunRegPath, QSettings::NativeFormat);
if (objRegSetting.contains(g_pszAutoRunHMI))
{
strErr = QObject::tr("已设置HMI自启动若需重新设置请先取消");
return false;
}
else
{
if (!objRegSetting.isWritable())
{
strErr = QObject::tr("注册表不可写,请确认是否具有权限!");
return false;
}
objRegSetting.setValue(g_pszAutoRunHMI, QString("\"") + strExec + QString("\""));
if (QSettings::NoError != objRegSetting.status())
{
strErr = QObject::tr("写入注册表失败!");
return false;
}
}
return true;
}
//----------------------------------------
//< 设置进程管理自启动
bool setSysStartupAutoStart(QString &strErr,QString path)
{
const QString strExec =QDir::toNativeSeparators
(path + "/AddSchtasksSysStarup.bat");
//< 判断文件存在
if (!QFile::exists(strExec))
{
strErr = QObject::tr("文件不存在!") + "\n" + strExec;
return false;
}
QString curWorkPath = QDir::currentPath();
QDir::setCurrent(path); // 切换工作路径
if(QProcess::execute(strExec) != QProcess::NormalExit)
{
strErr = QObject::tr("脚本执行失败!") + "\n" + strExec;
return false;
}
QDir::setCurrent(curWorkPath); // 恢复工作路径
return true;
}
bool setSysStartupAutoStartByVbs(QString &strErr,QString path)
{
QString vbsTxt;
vbsTxt += "Set WshShell = CreateObject(\"WScript.Shell\" )\n";
vbsTxt += QString("WshShell.Run \"") + "\"\"" + QDir::toNativeSeparators(path + "\\product\\" + QString(g_platform_dir_name) + "\\sys_startup.exe\"\" -hide") + "\"\n";
vbsTxt += "Set WshShell = Nothing";
QFile vbsFile( QDir::toNativeSeparators(QString(g_pszAutoStartSysStartupPath) ) );
if(!vbsFile.open(QFile::WriteOnly | QFile::Truncate))
{
strErr = QObject::tr("启动文件无法写入");
return false;
}
if(vbsFile.write(vbsTxt.toLocal8Bit()) != -1)
{
vbsFile.close();
return true;
}
else{
strErr = QObject::tr("启动文件无法写入");
vbsFile.close();
return true;
}
}
//----------------------------------------
//< 创建快捷方式
bool creatShortcut(QString &strErr,QString path)
{
QString prodPath = path + QDir::separator() + "product" + QDir::separator() + g_platform_dir_name;
//<桌面快捷方式
QFile::link(prodPath + "/sys_startup.exe", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).append("/").append("实时监控.lnk"));
//>桌面快捷方式
return true;
Q_UNUSED(strErr);
}
bool createStartProgram(QString &strErr,const QString& path)
{
QString prodPath = path + QDir::separator() + "product" + QDir::separator() + g_platform_dir_name;
QString platPath = path + QDir::separator() + "platform" + QDir::separator() + g_platform_dir_name;
//<开始菜单
QDir dir;
QString startMenuPath=QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)+"/EMS60";
dir.mkpath(startMenuPath);
QString startMenuNormalPath = startMenuPath + "/常用工具";
dir.mkpath(startMenuNormalPath);
QFile app;
app.link(platPath + "/sys_dog_auth_check.exe", startMenuNormalPath+"/超级狗检查.lnk");
app.link(prodPath + "/FesSim.exe", startMenuNormalPath+"/前置调试.lnk");
app.link(prodPath + "/debug_tool.exe", startMenuNormalPath+"/工程调试工具.lnk");
app.link(prodPath + "/sys_command.bat", startMenuNormalPath+"/命令窗口.lnk");
QString startMenuProjectPath = startMenuPath + "/工程建模";
dir.mkpath(startMenuProjectPath);
app.link(platPath + "/model_system_config.exe",startMenuProjectPath+"/系统建模.lnk");
app.link(platPath + "/model_studio.exe", startMenuProjectPath+"/设备建模.lnk");
app.link(platPath + "/hmi.exe", startMenuProjectPath+"/画面组态.lnk");
app.link(platPath + "/fbd_designer.exe", startMenuProjectPath+"/逻辑编程.lnk");
app.link(platPath + "/db_manager.exe", startMenuProjectPath+"/工程管理.lnk");
QString startMenuSystemPath = startMenuPath + "/系统监控";
dir.mkpath(startMenuSystemPath);
app.link(prodPath + "/sys_startup.exe", startMenuSystemPath+"/实时监控.lnk");
app.link(platPath + "/hmi_explorer.bat", startMenuSystemPath+"/人机界面.lnk");
app.link(prodPath + "/" + QString(UNINSTALL_EXEC_NAME), startMenuPath+"/系统卸载.lnk");
//>开始菜单
return true;
Q_UNUSED(strErr);
}
bool DelDir(QString &path)
{
if(path.isEmpty())
{
return false;
}
QDir dir(path);
if(!dir.exists())
{
return true;
}
dir.setFilter(QDir::AllEntries|QDir::NoDotAndDotDot);
QFileInfoList fileList=dir.entryInfoList();
foreach (QFileInfo fi, fileList)
{
if(fi.isFile())
{
fi.dir().remove(fi.fileName());
}
else
{
DelDir(fi.absoluteFilePath());
}
}
return dir.rmpath(dir.absolutePath());
}
//< 注册Mysql服务
bool regMysqlService(QString &path,QString &strErr)
{
bool bRet = false;
const QString strExec = QDir::toNativeSeparators
(path + "/mysqld.exe");
//< 判断文件存在
if (!QFile::exists(strExec))
{
strErr = QObject::tr("文件不存在!") + "\n" + strExec;
return false;
}
//< 打开服务控制管理器
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == hSCM)
{
strErr = QObject::tr("打开服务管理器失败,请确认是否具有权限!");
}
else
{
//< 判断服务是否已存在
SC_HANDLE hService = ::OpenService(hSCM, g_pTCharLauncherServiceName, SERVICE_QUERY_CONFIG);
if (NULL == hService)
{
//< 创建服务
//< 使用SERVICE_USER_XXX_PROCESS服务类型用户登录时启动不影响共享内存等的使用
//< 若使用SERVICE_WIN32_XXX_PROCESS等服务类型程序以system用户启动共享内存被隔离其他用户访问不到
//< todo 最好是实时库等使用共享内存、互斥锁的程序修改声明方式为Global突破用户间的隔离原因
//< 1、如上面说的SERVICE_USER_XXX_PROCESS是用户登录时才启动服务自启的实际意义打折扣
//< 2、多用户登录时会启动多个实例而实际上由于端口占用等原因是起不来的
//< 3、本程序停止服务时存在困难见下面unregSysService()中的注释。
hService = ::CreateService(
hSCM, g_pTCharLauncherServiceName, g_pTCharLauncherServiceName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
strExec.toStdWString().c_str(), NULL, NULL, NULL, NULL, NULL);
if (hService == NULL)
{
strErr = QObject::tr("注册服务失败,请确认是否具有权限!");
}
else
{
SERVICE_DESCRIPTION stSrvDesc;
TCHAR szDesc[] = _T("MySql");
stSrvDesc.lpDescription = szDesc;
if (::ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &stSrvDesc))
{
bRet = true;
}
::CloseServiceHandle(hService);
}
}
else
{
strErr = QObject::tr("Mysql服务已启动");
::CloseServiceHandle(hService);
}
::CloseServiceHandle(hSCM);
}
return bRet;
}
bool regUninstallReg(const QString &iconPath,const QString &version,const QString &uninstallerPath,QString &strErr)
{
QSettings objRegSetting(g_pszRegUninstallRegPath, QSettings::NativeFormat);
if(!objRegSetting.isWritable())
{
strErr = "cannot write to registry";
return false;
}
objRegSetting.setValue("DisplayIcon",iconPath); // 需要自定义
objRegSetting.setValue("DisplayName","DiCS-EMS60");
objRegSetting.setValue("DisplayVersion",version); // 需要拼接
objRegSetting.setValue("Publisher","BYD CO.LTD");
objRegSetting.setValue("UninstallString",uninstallerPath); //需要拼接
return true;
}
} //< namespace iot_sys
#endif //< #ifdef OS_WINDOWS