/********************************************************************************** * @file SetupFuncWindows.cpp * @brief Windows系统设置函数 * @author yikenan * @versiong 1.0 * @date **********************************************************************************/ //< 仅在Win系统下编译 #ifdef OS_WINDOWS #include #include #include #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