EasyPro 升级包设计文档
基于 Advanced Installer 19.x 构建 · 最终产品:EasyPro.exe
基于 Advanced Installer 19.x 构建,最终产品为 EasyPro.exe。本文档同步至 V2.1.1 实际代码:MySQL 前置检查、失败继续策略、动态端口回填、SQL 多文件、版本号两层写入。
提供从已安装的智控平台旧版本向新版本无缝升级的能力,不涉及首次安装场景。
核心区别:升级 ≠ 重装
升级包不重新部署完整组件,而是通过 资源_{版本号} 文件夹中的增量升级脚本,按版本顺序依次执行。资源/ 目录(完整安装资源)在升级过程中不被使用。
| 字段 | 值 |
|---|---|
| 产品名称 | 智控平台 |
| UpgradeCode | {4A49D8CC-5A22-466E-A867-6E95AD659547}(与安装包相同) |
| 升级包文件名 | EasyPro.exe |
| 语言 | 中文(zh) |
| 文件 | 用途 |
|---|---|
v2.1.1_upgrade.aip | 升级包工程(基于 v2.1.1_install.aip 派生),构建出 EasyPro.exe |
v2.1.1_install.aip | 上游安装包工程,升级包仅继承其构建参数(UAC、提取目录等) |
资源_{版本号}/ | 升级核心目录,每个版本包含 upgrade_to_{版本号}.ps1 及增量文件 |
版本通用资源/ | 版本通用资源 — 每个版本都会变更的大体积文件(yuntrol、build、JAR 等),集中存放避免重复打包 |
资源/ | 完整安装资源,升级流程中不使用 |
| 参数 | 值 |
|---|---|
| 打包类型 | PackageType=1 — 单文件 EXE(Self-Extracting) |
| 提取目录 | %APPDATA%\浙江源创智控技术有限公司\智控平台 2.0.0\install |
| UAC 级别 | 2(需要管理员权限) |
deploy_common.ps1部署脚本service/*.jarJava 业务 JAR 包(~100 MB,每版必变)upgrade_to_2.0.0.ps1升级总控脚本upgrade_to_2.1.0.ps1upgrade_to_2.1.1.ps1部署 EasyProTool + 部署 Qdrant + 数据升级EasyPro 运维助手(EasyProTool,桌面端 Tauri 应用,创建桌面快捷方式)和 Qdrant 向量数据库(注册为 Windows 服务 SctechQdrantService)。两者都通过 组件新增\ 下各自的 部署{组件名}.ps1 完成部署。
前端构建产物(yuntrol、build)和业务 JAR 是每个版本迭代都几乎必然会变更的资源,且体积巨大(合计约 1 GB)。若将这些大文件复制到每个 资源_{版本号}/ 目录中:
- 有 N 个版本 → 包体积增加 N × 1 GB
- 随着版本积累 → 升级包从几百 MB 膨胀到数 GB
- 每个版本的增量升级脚本需要维护这些大文件的拷贝逻辑,容易出错
解决方案:将这些大体积文件集中存放在 版本通用资源/ 中,每个升级版本目录 资源_{版本号}/ 只存放版本特有的增量变更(配置文件、SQL 脚本等)。无论有多少个版本,大文件只有一份。
版本通用资源/ 内的路径结构完全镜像安装后的 [APPDIR] 目录结构:
| 版本通用资源内路径 | 目标安装路径 |
|---|---|
nginx/html/yuntrol/ | [APPDIR]\nginx\html\yuntrol\ |
optiView/build/ | [APPDIR]\optiView\build\ |
service/*.jar | [APPDIR]\service\ |
部署脚本直接基于路径对应关系操作,无需额外维护映射表。
| 资源类型 | 操作方式 | 说明 |
|---|---|---|
| 目录型(yuntrol、build) | 先停止对应服务 → 强制终止残余进程(node.exe、java.exe)→ Remove-DirectorySafely 安全删除目录 → Copy-Item -Recurse 拷贝 | 目录内文件可能增减或重命名,且需先释放文件锁;残余进程(如手动启动的 node.exe)会阻止目录删除 |
| 文件型(*.jar) | 先停止 Java 后端 → 逐个删除同名旧文件 → 拷贝新文件 | JAR 运行时被 JVM 锁定,必须先停止服务 |
deploy_common.ps1不再接受-InstallDir参数,安装路径强制从注册表HKLM:\SOFTWARE\浙江源创智控技术有限公司\智控平台\Path读取- 读取失败时报错中止
- 调用者可通过
-SourceDir参数显式传入资源目录 - 如果未传入,自动使用本脚本所在目录(
版本通用资源/)
资源_{版本号}/ 目录不应再包含大型前端文件(yuntrol、build)和 JAR 包。这些文件统一放在 版本通用资源/ 中,由 deploy_common.ps1 统一部署,避免在每个版本目录中重复打包导致体积膨胀。
升级包通用脚本\运行增量升级.ps1(升级包工程 v2.1.1_upgrade.aip 自定义操作调用)。该脚本自检管理员权限、从注册表读取安装路径、做 MySQL 服务前置检查后,依次扫描 资源_{版本号}、执行各版本升级脚本、部署版本通用资源、更新注册表版本号,最后汇总成功/失败步骤并打印总耗时。
升级包启动后,按照以下步骤执行:
EasyPro.exeHKLM:\SOFTWARE\浙江源创智控\智控平台\Path 读取安装路径;非管理员时自动请求提权重启EasyProVersion 键值(如 "2.0.0")ExtractDir资源_{版本号} 文件夹upgrade_to_{版本}.ps1资源_2.0.0 → 资源_2.1.0 → 资源_2.1.1 … 某版本失败时继续执行下一个(尽可能多执行,最后汇总失败步骤)版本通用资源/deploy_common.ps1,依次部署:①
nginx/html/yuntrol 停 Nginx→删旧→拷新;② optiView/build 停 OptiView→杀 node.exe→安全删→拷新;③ service/*.jar 停 Java→删旧 jar→拷新→重启必须放在增量升级后,确保最新大文件最终覆盖;覆盖
application-local.yml 后用中间件实际端口动态回填(详见 2.7 节)EasyProVersion = "2.1.1"。各升级脚本内也写自己版本号,此处由总控用「已执行的最高版本」做最终覆盖,保证一致exit 0,存在失败 exit 1升级包启动后读取注册表:
路径: HKLM:\SOFTWARE\浙江源创智控技术有限公司\智控平台 键名: EasyProVersion
PowerShell 获取方式:
$reg = Get-ItemProperty -Path "HKLM:\SOFTWARE\浙江源创智控技术有限公司\智控平台" $currentVersion = $reg.EasyProVersion
该键由安装脚本在首次安装时写入(值为产品版本号),后续每次升级完成后由升级总控脚本同步更新。
扫描升级包提取目录下所有匹配 资源_(\d+\.\d+\.\d+) 模式的文件夹,提取版本号并按语义版本排序。
将排序后的可用版本列表与当前版本比较,仅执行 版本号 > 当前版本 的升级脚本。若无可升级版本,则跳过所有步骤直接退出。
升级完成后,需要在以下位置记录新版本号:
| 位置 | 键/字段 | 说明 |
|---|---|---|
| 注册表(权威) | HKLM\...\智控平台\EasyProVersion | 由各子脚本和总控脚本分别写入(两层写入,见 2.3.1) |
| 数据库(辅助) | sys_platform_info.cur_platform_version | 由 0_common.sql 在数据升级时更新(不是脚本直接写数据库),供运维助手下发版本查询 |
早期文档约定「子脚本不写版本号,统一由总控写」。实际代码(upgrade_to_2.1.1.ps1)在结尾成功路径内也写了 EasyProVersion=2.1.1。文档按代码现状描述。
| 写入层 | 时机 | 写入的值 | 作用 |
|---|---|---|---|
| 子脚本层 | 每个 upgrade_to_{版本}.ps1 全部步骤成功后 | 该版本号(如 2.1.1) | 单独运行该脚本时也能正确记录版本;并作为总控最终写入的"候选值" |
| 总控层 | 所有子脚本 + 版本通用资源部署完毕后 | 已成功执行的最高版本号($lastVersion) | 覆盖最终值,确保多版本跨版本升级时记录的是最高版本 |
两层写入的最终值一致(单版本升级场景下完全相同),总控层用最高版本覆盖是权威写入。子脚本内写入失败只记 WARN 不中止。
每个 upgrade_to_{版本号}.ps1 脚本须遵守以下约定:
| 要求 | 说明 |
|---|---|
| 参数签名 | 接受 -InstallDir <string> 参数(安装路径),由总控脚本传入;未传入时自行从注册表读取(便于独立运行) |
| 幂等性 | 脚本应可重复执行而不破坏已有数据(必要时做存在性检查后再操作) |
| 日志 | 输出到 upgrade_to_{版本号}.log |
| 退出码 | 成功返回 0,失败返回非零值(exit 1) |
| 管理员权限 | 脚本内部自行检测并提权 |
| 步骤组织 | 用内置 Invoke-Step -StepName <名> -ScriptPath <脚本> 调用各步骤子脚本,每步独立判定成功/失败 |
| 版本号写入 | 全部步骤成功后,自行写入注册表 EasyProVersion(见 2.3.1 两层写入) |
| 工作目录 | 脚本所在目录即 资源_{版本号} 文件夹,相对路径指向 数据更新/、组件更新/、组件新增/ |
总控脚本 运行增量升级.ps1 对单个版本升级失败采用继续执行策略,而非立即中止:
- 某个
upgrade_to_{版本}.ps1退出码非 0 或抛异常 → 记入$failSteps,继续执行下一个版本和后续步骤(版本通用资源部署、注册表更新) - 版本通用资源
deploy_common.ps1部署失败 → 记入$failSteps,不中止 - 注册表版本号更新失败 → 记入
$failSteps,不中止 - 全部结束后:
$failSteps为空则exit 0;存在失败则exit 1 - 注册表版本号只在
$lastVersion(最后一个成功执行的版本)非空时才更新
跨多版本升级时,中间某个版本失败不应阻塞后续版本,让尽可能多的升级执行到位,最后由运维根据汇总清单针对性修复。
运行增量升级.ps1 在扫描升级资源前,强制检查并启动 MySQL 服务(升级依赖数据库执行 SQL):
| MySQL 服务状态 | 处理 |
|---|---|
不存在(SctechCMySQL 未注册) | 报错并 exit 1 中止 |
| 已运行 | 跳过 |
| 未运行 | 发起 Start-Service,最多重试 5 次、每次间隔 3 秒等待变为 Running |
| 重试耗尽仍未启动 | 报错并 exit 1 中止 |
服务名固定为 SctechCMySQL(取自《各服务配置信息速查手册》)。
deploy_common.ps1 在覆盖 service\config\ 子目录时,对 application-local.yml 做了动态端口回填特判,避免升级把安装时动态分配的中间件端口冲回默认值:
触发场景:service\config\ 子目录覆盖前,先把旧 application-local.yml 备份到 $env:TEMP\application-local.old.<guid>.yml;新 yml 覆盖完成后调用 Restore-DynamicPorts。
| 中间件 | 权威源(运行时生成的本地配置) | 回退源 | 替换的默认值 |
|---|---|---|---|
| MySQL | {InstallDir}\mysql\my.ini 的 port= 行 | 旧 yml 的 jdbc:mysql://127.0.0.1:<port> | 3306(全局替换所有 jdbc url) |
| Redis | {InstallDir}\Redis\redis.windows.conf 的 port 行 | 旧 yml 的 spring.data.redis.port | 6379(精确替换 port: 行) |
| InfluxDB | {InstallDir}\influxdb2\influxdb2\config.toml 的 http-bind-address | 旧 yml 的 http://127.0.0.1:<port> | 8086(全局替换) |
| 服务自身 | 无中间件侧权威源 | 旧 yml 的首行 port: | 1998(精确替换,值≠1998 才替换) |
- 端口行替换统一走
Replace-PortLine:用[regex]::Replace+MatchEvaluator脚本块,通过$m.Groups[n].Value显式取捕获组,绝不在替换串中使用$1/$2字面量(PowerShell 会把'$1'+'1998'贪婪解析为$11998,写出非法 yml) - 全程失败只告警(
Write-Log "WARN"),绝不中断部署(端口回填是增强,不是硬约束) - 写回用 UTF-8 无 BOM,与 yml 原编码保持一致
- 回填前自动备份新 yml 为
application-local.yml.deploy.bak,便于回滚
| 方面 | 首次安装 | 升级 |
|---|---|---|
| 资源依据 | 资源/(完整组件包) | 资源_{版本号}/(增量升级脚本) |
| 前置条件 | 无,从零部署 | 需已安装旧版本(注册表可查 Path + EasyProVersion) |
| UI 交互 | 完整安装向导(DbConfig / RedisConfig) | 无数据库配置界面,沿用已有配置 |
| 文件覆盖 | 全部新部署 | 仅执行增量脚本中指定的变更 |
| 组件注册 | Windows 服务全新注册 | 增量脚本中只增/更新必要的服务 |
| 路径选择 | 用户可选择安装路径 | 从注册表读取已有安装路径 |
| 版本判断 | 无 | 通过注册表 EasyProVersion 键确定升级起点 |
| 版本写入 | 安装脚本写入 EasyProVersion(基础版本) | 子脚本 + 总控两层写入(见 2.3.1) |
| MySQL 前置检查 | 安装时由安装脚本初始化 | 升级前强制检查并启动 MySQL(见 2.6) |
升级包不通过 UI 接收输入,所有参数来自已安装环境:
| 参数 | 来源 |
|---|---|
| 安装路径 | 注册表 HKLM:\SOFTWARE\浙江源创智控技术有限公司\智控平台\Path |
| 当前版本号 | 注册表 HKLM:\SOFTWARE\浙江源创智控技术有限公司\智控平台\EasyProVersion(不存在或为空视为 0.0.0) |
| 提取目录 | 优先注册表 HKLM:\SOFTWARE\浙江源创智控技术有限公司\智控平台升级包\Path,失败回退到安装路径 |
MySQL 及其他服务配置无需作为升级输入参数,因为增量升级脚本可按需从 application-local.yml 获取,版本通用资源部署阶段还会用动态端口回填(2.7)校正中间件端口。
upgrade_to_{版本号}.ps1【必须】该版本升级脚本(由总控依次调用)upgrade_data.ps1扫描本目录所有 *.sql,按前缀数字顺序执行0_common.sql数字越小越先执行1_mqtt.sql2_app.sql3_modbus.sql4_bacnet.sql部署{组件名}.ps1组件更新/ 中绝对不应包含 yuntrol、build 目录或 JAR 包。这些每个版本都会变更的大体积文件(合计约 1 GB)统一存放在 版本通用资源/ 中,由总控脚本在增量升级全部执行完毕后通过 deploy_common.ps1 统一部署(放在升级后执行,确保通用资源覆盖旧版文件)。各版本升级脚本应只关注版本特有的增量变更(配置文件修改、数据脚本、服务注册等)。
这样做的好处:
- 包体积不随版本数量线性增长 — N 个版本的升级包中,大文件只有一份
- 避免重复劳动 — 每个版本不需要重复写大文件的拷贝逻辑
- 降低出错概率 — 删除整目录再拷贝的方式比逐文件覆盖更可靠
数据更新/ 下所有 .sql 文件由 upgrade_data.ps1 统一调度执行:
- 命名规则:
{数字}_{业务名}.sql(如0_common.sql、1_mqtt.sql),数字越小越先执行 - 数据库引用:使用完全限定名(
`ibms-system`.`sys_menu`);涉及存储过程的 SQL 文件须在CREATE PROCEDURE前显式USE指定数据库,避免ERROR 1046 No database selected - 执行隔离:每个 SQL 文件独立执行,单独记录成功/失败;
upgrade_data.ps1全部成功exit 0,有失败exit 1 - 幂等保护:推荐用存储过程 + 游标遍历
sys_project+INSERT ... SELECT ... WHERE NOT EXISTS模式,保证可重复执行
| 序号 | 文件 | 职责 |
|---|---|---|
| 0 | 0_common.sql | 更新 sys_platform_info 平台版本号至 v2.1.1;字段类型修订;为每个项目插入「树形结构默认展开」sys_config |
| 1 | 1_mqtt.sql | MQTT 驱动数据升级:为每个项目插入 iot_driver / iot_driver_attribute / iot_driver_point_attribute(含全局 iot_driver_config) |
| 2 | 2_app.sql | App 端菜单:sys_menu 增加 url、is_app 字段;为每个项目插入能源管理 / 智慧告警 / 系统日志业务菜单 |
| 3 | 3_modbus.sql | Modbus 驱动补充 writeFunctionCode / writeCodeSwitchMode 属性 |
| 4 | 4_bacnet.sql | BACnet IP 驱动数据升级(参考 1_mqtt 模式插入驱动及属性) |
新增 SQL 文件时,序号延续递增(5_xxx.sql...),并在此表登记。
<# .SYNOPSIS EasyPro V{版本号} 升级脚本 .DESCRIPTION 按顺序执行当前版本的所有升级步骤: - 组件更新(拷贝新文件覆盖旧文件) - 组件新增(拷贝新组件到安装目录并安装服务) - 数据升级(执行 SQL 脚本) 版本号写入(升级完成后更新注册表 EasyProVersion 键) .NOTES 需要以管理员权限运行。 由升级总控脚本调用,传入 -InstallDir 参数。 #> param( [string]$InstallDir # 安装路径,由总控传入 ) $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition $LogFile = Join-Path $ScriptDir "upgrade_to_{版本号}.log" function Write-Log { ... } function Invoke-Step { ... } # 权限检测、日志标题等... # 步骤 1: 组件更新 # Invoke-Step "更新 xxx" "组件更新\xxx.ps1" # 步骤 2: 组件新增 # Invoke-Step "部署 yyy" "组件新增\yyy\部署yyy.ps1" # 步骤 3: 数据升级 # Invoke-Step "数据升级" "数据更新\upgrade_xxx.ps1" # 步骤 4: 更新注册表版本号 # Set-ItemProperty -Path "HKLM:\SOFTWARE\浙江源创智控技术有限公司\智控平台" ` # -Name "EasyProVersion" -Value "{版本号}" # 结果汇总...
升级包提取到临时目录后,由总控脚本 升级包通用脚本\运行增量升级.ps1 统筹所有升级步骤,由升级包工程 v2.1.1_upgrade.aip 的自定义操作(Custom Action)在文件提取完成后调用。
完整实现见 升级包通用脚本/运行增量升级.ps1。以下为关键骨架(省去日志、汇总、提权等细节),展示真实控制流与失败处理策略。
$RegPath = "HKLM:\SOFTWARE\浙江源创智控技术有限公司\智控平台" $UpgradeRegPath = "HKLM:\SOFTWARE\浙江源创智控技术有限公司\智控平台升级包" $successSteps = @(); $failSteps = @() # 0. 管理员权限自检(非管理员则 RunAs 提权重启) # 0.1 读取安装路径(注册表 Path 键,失败 exit 1) $InstallDir = (Get-ItemProperty -Path $RegPath -Name "Path").Path # 0.2 当前版本(缺失/为空视为 0.0.0,即视为全新环境全量执行) $currentVersion = try { (Get-ItemProperty -Path $RegPath -Name "EasyProVersion").EasyProVersion } catch { "0.0.0" } # ★ 前置检查:启动 MySQL 服务(不存在 exit 1;未运行则启动,最多 5 次重试间隔 3 秒) Ensure-MysqlRunning # 见 2.6 # 0.3 提取目录:优先升级包注册表,失败回退安装路径 $ExtractDir = try { (Get-ItemProperty -Path $UpgradeRegPath -Name "Path").Path } catch { $InstallDir } # 步骤 1/5:扫描 资源_{版本号} $upgradeDirs = Get-ChildItem -Directory (Join-Path $ExtractDir "资源_*") | Where-Object { $_.Name -match '^资源_(\d+\.\d+\.\d+)$' } | Sort-Object { [Version]$matches[1] } # 步骤 2/5:筛选版本号 > 当前版本,并依次执行(失败继续,非中止) $lastVersion = $null foreach ($dir in $upgradeDirs) { $verString = $matches[1] # 注意:$matches 在 Where 后可能失效,实际代码用显式 rematch if ([Version]$verString -le [Version]$currentVersion) { continue } $scriptPath = Join-Path $dir.FullName "upgrade_to_${verString}.ps1" try { & $scriptPath -InstallDir $InstallDir *>&1 | CaptureToLog if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { $failSteps += "升级到 $verString(退出码 $LASTEXITCODE)" } else { $lastVersion = $verString # 记录最后一个成功版本 $successSteps += "升级到 $verString" } } catch { $failSteps += "升级到 $verString 异常: $_" } # ★ 注意:不 throw,继续下一个版本 } # 步骤 3/5:部署版本通用资源(含动态端口回填特判,见 2.7) $commonScript = Join-Path $ExtractDir "版本通用资源\deploy_common.ps1" if (Test-Path $commonScript) { & $commonScript -SourceDir (Join-Path $ExtractDir "版本通用资源") # 失败仅记入 failSteps,不中止 } # 步骤 4/5:更新注册表版本号(用最后一个成功版本做最终覆盖) if ($lastVersion) { try { Set-ItemProperty -Path $RegPath -Name "EasyProVersion" -Value $lastVersion } catch { $failSteps += "注册表版本号更新失败: $_" } } # 步骤 5/5:结果汇总(成功/失败步骤清单 + 总耗时) if ($failSteps.Count -eq 0) { Write-Host "[完成] 全部完成"; exit 0 } else { Write-Host "[警告] 部分失败"; exit 1 }
| 项 | 说明 |
|---|---|
| 脚本路径 | 升级包通用脚本\运行增量升级.ps1(被打包进升级包,由 v2.1.1_upgrade.aip 自定义操作调用) |
| 同级脚本 | 检验版本.ps1(升级首个校验:未安装则退出;已安装版本 ≥ 升级包版本时禁止降级/重复升级并退出,接收 -UpgradeVersion 参数)、启动所有服务.ps1(升级收尾:遍历已知服务列表启动未运行的服务)、卸载所有服务.ps1(升级前可选卸载服务,扫描安装目录所有 uninstall.bat 并按"应用→中间件→数据库"优先级执行) |
| 日志 | 升级包通用脚本\运行增量升级.log(脚本同目录) |
| 提权 | 内部自检,非管理员时 Start-Process -Verb RunAs 提权重启,等子进程退出后用其 ExitCode 退出 |
运行增量升级.ps1总控入口(扫描资源_*/执行升级/部署通用资源/更新版本号/汇总)检验版本.ps1升级首个校验(未安装/禁止降级/禁止重复升级则退出)卸载所有服务.ps1扫描安装目录所有 uninstall.bat,按优先级停止并删除服务启动所有服务.ps1升级收尾,遍历已知服务列表启动未运行的服务这四个脚本都被打包进升级包工程;安装包工程(v2.1.1_install.aip)同样打包了它们(用于首次安装后执行增量升级,详见安装包文档)。
资源_2.0.0 和 资源_2.1.0 都存在,从 V2.0.0 起需要两个版本依次执行。资源/ 目录不参与升级资源_{版本号} 有效。EasyProVersion 由子脚本(各自版本号)和总控脚本(最高版本号)分别写入,最终以总控写入为权威;数据库 cur_platform_version 由 0_common.sql 辅助更新(见 2.3.1)。版本通用资源/ 在每次增量升级全部执行完毕后由总控脚本部署,以「Remove-DirectorySafely 安全删除旧目录 → 拷贝新目录」的方式覆盖 yuntrol、build(删除前会强制终止残余 node.exe 进程防止文件锁),以「删除旧 JAR → 拷贝新 JAR」的方式覆盖 JAR;service\config\ 子目录覆盖后还会做动态端口回填(2.7)。放在升级后执行是为了确保最新大文件最终覆盖到位,防止升级组件更新中的旧文件覆盖新通用资源。所有 资源_{版本号}/ 的 组件更新/ 中绝对不得包含这些大文件,否则违背该设计的初衷。SctechCMySQL),启动失败则中止(见 2.6)。exit 1 提示有失败(见 2.5)。- 打开
v2.1.1_upgrade.aip(基于v2.1.1_install.aip派生) - 确认所有
资源_{版本号}目录及其升级脚本已就绪 - 在 Advanced Installer 中执行构建(Build → Build)
- 构建产物:
EasyPro.exe
| 测试项 | 预期结果 |
|---|---|
| 从未安装的环境执行升级 | 注册表 Path 不存在,提示未检测到安装并 exit 1 |
| 从旧版本升级(如 V2.0.0 → V2.1.1) | 正确扫描版本序列,依次执行各版本升级脚本,注册表 EasyProVersion 更新为 2.1.1 |
| 从同版本执行升级(如 V2.1.1 → V2.1.1) | 无可升级版本,exit 0 完成 |
| 从高版本执行升级(回退) | 筛选结果为空,跳过所有升级步骤 |
| MySQL 服务未启动 | 总控自动启动(最多 5 次重试),启动成功后继续升级 |
| MySQL 服务不存在 | 报错 exit 1 中止(提示 MySQL 未正确安装) |
| 单个版本升级失败 | 记入失败清单,继续执行后续版本,末尾 exit 1 汇总(失败继续策略) |
| 动态端口回填 | 覆盖 yml 后,MySQL/Redis/InfluxDB 端口被回填为中间件实际端口(非默认 3306/6379/8086) |
| 升级过程中断后重启 | 已执行的版本脚本是幂等的(SQL 用 WHERE NOT EXISTS、组件覆盖用删除-拷贝),不会造成破坏 |
| 升级后注册表版本号 | HKLM\...\智控平台\EasyProVersion 已更新为最后一个成功执行的版本号 |
| 升级后服务可用 | 所有 Windows 服务正常运行,端口配置正确 |
| 数据保留 | MySQL / InfluxDB / Redis 中的用户数据不被清除 |
最后更新:2026-07-28 | 同步至 V2.1.1 实际代码:MySQL 前置检查、失败继续策略、动态端口回填、SQL 多文件、版本号两层写入