372 lines
12 KiB
C++
372 lines
12 KiB
C++
|
||
/**********************************************************************************
|
||
* @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
|