简介AutoUpgrader Pro v5.02是一套面向Delphi 12.3开发者的自动升级控件包专门解决桌面应用在线检测更新、下载与安装升级的常见需求适合具备一定基础的中高级程序员直接集成或进行二次开发。整个资源包共计158个文件核心组成既有pas源码、dcu编译单元也有dpk包工程、dfm窗体与res资源文件并辅以示例exe与说明文档不同后缀文件分别承担源码修改、快速编译和界面配置等角色整体压缩后仅3.25MB结构紧凑、层次清晰便于按需取用。目前已有95人学习/下载。资源特别附带了完整的演示工程并集成了分别处理升级判断、HTTP下载、后台线程调度等任务的核心单元清楚展示了各功能模块的实现脉络。通过阅读和运行这些代码可以更快掌握控件调用方式、事件处理与配置流程并将其无缝集成到自己的Delphi项目中减少自行搭建升级模块的重复工作。1. 自动升级不是“下载替换”那么简单AutoUpgrader Pro v5.02 在 Delphi 12.3 里解决什么问题老客户电脑上装的是去年发布的版本你刚把 Delphi 12.3 下的新 exe 编译出来总不能一个电话一个电话地让人远程重装。桌面软件最怕的就是客户端分散在几十台机器上版本不一致业务数据口径乱成一锅粥。标题里的 AutoUpgrader Pro v5.02 to D12.7z就是一个专门给 Delphi 12RAD Studio 12.x编译的自动升级控件包程序启动时检查服务器上的版本元数据发现新版本就下载更新包、替换正在运行的 exe、再自动重启。这套方案适合做进销存、ERP、行业工具这类传统桌面客户端的 Delphi 开发者省掉自建升级通道的重复工作也避免“老用户永远不升级”这个最琐碎又最不能出错的环节。2. 拿到 .7z 包先别急着拖控件AutoUpgrader Pro v5.02 to D12 的安装与包结构先拆标题。“v5.02”是控件版本号“to D12”表示这包面向 Delphi 12 编译和标题里的 Delphi 12.3 同属 RAD Studio 12.x 时代。后缀 .7z 说明归档用的是 7-Zip。很多 Delphi 第三方包喜欢用 7z 压缩源码解压后你最好先不要去找 .exe 安装程序——多数这类包给的是源码工程需要你自己在 IDE 里编译注册。2.1 先认包结构dpk、dcu、bpl 各自该放哪拿到 7z 后第一步不是点开某个 .dpr 瞎看而是整体扫一眼目录。常见结构大约是这样各家打包习惯略不同但主干就这几块路径内容你的动作Packages\AutoUpgraderProD12.dpk面向 Delphi 12 的包工程在 IDE 中打开并编译、InstallSource*.pas控件源码编译后自动生成 dcu必要时加入 Library pathlib\d12\win32、lib\d12\win64预编译 dcu编译 Win64 工程时必须有 win64 那份Demos、Help示例工程与文档建议保留遇到属性命名差异时翻 Help为什么先花时间认结构Delphi 第三方控件的安装方式其实分两种一种是包工程编译后生成 .bpl直接在 IDE 里 Install组件会出现在 Tool Palette另一种只给源码你需要把源目录或预编译 dcu 目录加进库搜索路径。分不清这两种后面出了“找不到 dcu”的问题时你会不知道是路径没配还是控件本身和 D12.3 不兼容。注意看文件名后缀。包里可能同时带 D10、D11、D12 多个版本工程务必选 D12 的 .dpk。带 D11 的包即使能勉强打开编译时也可能因为 RTL 接口差异报一堆错没必要给自己加戏。2.2 用 IDE 编译并安装 dpkDelphi 12.3 库路径三处要同步推荐在 IDE 里安装最省事。步骤是这样用 Delphi 12.3 打开 AutoUpgraderProD12.dpk。在 Project Manager 里选中包项目右键 Compile先生成 .bpl 和 .dcp。这一步只验证源码能否在当前版本编译通过。编译成功后右键 Install控件注册到 IDE 的 Tool Palette。如果 Compile 时报找不到某个 .pas 或 .dcu把 Source 目录加到 Tools Options Environment Options Delphi Options Library Library path。加路径时一定要看界面右上角的 Platform 下拉框。Delphi 12.3 的 Library path 按 32-bit Windows 和 64-bit Windows 分开管理两个平台都要各加一次。全部弄完关闭重开工程再确认 Tool Palette 里有没有 AutoUpgrader 相关组件。这六步里最容易翻车的是第 5 步。Delphi 12.3 默认对 Win64 工程已经有完整工具链但如果你只在 32-bit 平台下加了 dcu 路径Win64 编译时 IDE 不报缺文件运行时才提示找不到单元。这种“能编不能跑”最耗时间。保险起见把 lib\d12\win32 和 lib\d12\win64 分别加到对应平台下别嫌啰嗦。提示装完控件第一次拖到窗体上Delphi 可能弹窗问是否把相关搜索路径写进工程选项选“是”。这样团队里别人打开工程时不需要手动配全局路径减少了交接成本。2.3 命令行编译用 MSBuild 在 CI 里装出控件包如果团队有统一构建环境或者你想把“给机器装控件”变成一条可执行命令可以走命令行编译。Delphi 自带 rsvars.bat 用来初始化命令行编译环境然后用 MSBuild 编包工程。call C:\Program Files (x86)\Embarcadero\Studio\23.0\bin\rsvars.bat msbuild AutoUpgraderProD12.dproj /p:ConfigRelease /p:PlatformWin32 msbuild AutoUpgraderProD12.dproj /p:ConfigRelease /p:PlatformWin64这段命令里rsvars.bat 把 BDS、DCC、库路径等环境变量带进当前 cmd 会话后面的 msbuild 编译 dproj 包工程。/p:ConfigRelease指用 Release 配置/p:Platform分别指定 32 位和 64 位输出。注意 .bat 前的 call 不能省直接执行 rsvars.bat 会在单独的子进程中完成当前窗口拿不到环境变量。命令行的结果是在包项目输出目录里生成 .bpl 和 .dcp但它不会帮你把组件注册进 IDE。真正要 Install还是要到 Delphi IDE 里点一次。所以在 CI 里我更常的用法是编译验证包能出不报错就继续打包交付团队团队成员拿到 dproj 后自己在 IDE 里 Install。如果你想让 CI 连 Install 也做掉要用注册表或工具 API 操作超出普通项目范围不推荐硬啃。3. 把升级逻辑接进程序AutoUpgrader 四个核心参数与检查流程控件装好下一步不是拖上去就完事。自动升级的链路是启动时比较本地版本和远端版本一致就安静跑不一致才下载更新包。控件“自动”的前提是你把四个信息告诉它服务器地址、版本文件名、本地版本文件、以及升级完成后要不要重启。这一章我把接入的代码骨架和几个关键时机讲透。3.1 四个必填项和两个触发时机AutoUpgrader 这类非可视组件运行期没有自带界面除非你主动调用它的更新窗口。关键属性在不同版本里命名略有差异最终以你安装包里的 Help 和 Demo 工程为准但职责基本一致FilesURL服务器上存放版本元数据和更新包的目录必须是完整 URL末尾带斜杠VersionFileName服务器上的版本文件名常见约定是 version.iniLocalVersionFile客户端记录当前版本的本地文件我一般放在程序目录下AutoCheck / CheckAtStartup程序启动时是否自动检查RestartAfterUpdate更新下载并替换完成后是否自动重启正式程序。两个事件触发时机要分开处理它们是接入业务逻辑的切入点。OnUpdateAvailable 在检查到新版本时触发这里决定“弹窗询问”还是“静默强制”OnUpdateDownloaded 在更新包下载并替换完成后触发这里适合做缓存清理、状态复位或写审计日志。我一般把 FilesURL 指向内网更新服务器下的固定目录VersionFileName 固定叫 version.ini这样前后端维护同一套约定发版脚本和后端同事都容易对接。3.2 检查更新的内部流程元数据、下载、替换、重启接代码前先理解控件内部在做什么启动后读取本地版本文件后台请求服务器上的 version.ini比较版本号有新版本则下载更新包完整性校验通过后替换正在运行的 exe再拉起新进程。核心代码差不多是下面这样procedure TMainForm.FormCreate(Sender: TObject); begin AutoUpgrader1.FilesURL : http://update.example.com/erp/; AutoUpgrader1.VersionFileName : version.ini; AutoUpgrader1.LocalVersionFile : localver.ini; AutoUpgrader1.AutoCheck : True; AutoUpgrader1.RestartAfterUpdate : True; end; procedure TMainForm.AutoUpgrader1UpdateAvailable(Sender: TObject; NewVersion: string); begin if IsForceUpgrade(NewVersion) then AutoUpgrader1.DownloadUpdate // 强制升级不弹窗 else if MessageDlg(发现新版本 NewVersion 是否更新, mtConfirmation, mbYesNo, 0) mrYes then AutoUpgrader1.DownloadUpdate; end;逻辑说明FormCreate 里把连接信息配好AutoCheck 置 True 后控件会在后台线程检查不阻塞主窗体。检查到新版本时进入 UpdateAvailable 事件这里由你决定是弹窗还是强制下载用户确认或满足强制条件后调用 DownloadUpdate 开始下载。RestartAfterUpdate 为 True 时替换完成后控件会主动退出现有进程并启动新进程。参数说明FilesURL 的路径一旦写错检查会静默失败或者报连接错误调试时先在浏览器里直接打开 version.ini 确认可访问AutoCheck 建议保持 True但并不意味着启动就必须立刻下载检查本身很轻量下载动作才占带宽。RestartAfterUpdate 设 False 时需要你自己管理重启时序多数情况下没必要省这条配置。3.3 常见误用把 AutoUpgrader 当通用下载器我见过有同事把这类自动升级控件当成通用下载器用来下 dll、下资源文件、下视频素材。后果是版本元数据里根本没有版本号文件一改名就反复下载覆盖程序运行到一半资源被替换界面直接崩。AutoUpgrader 的服务端约定围绕“程序自升级”设计它处理的是主进程替换不是通用 CDN 下载职责。下载业务资源请单独写下载线程挂断点续传和哈希校验升级控件只负责一件闭环确认新版本、下载更新包、替换 exe、重启。另一个常见倾向是把“启动检查”配成“启动必更新”用户在内网带宽紧张时登录前先被更新流程卡住。我会在 OnUpdateAvailable 里判断业务类型修复关键 bug 的版本强制升加了小功能的新版本先弹窗让用户选。用户体验顺了升级率反而更高。4. 服务器端的版本清单与增量包生成从文件约定到双平台发布自动升级的另一半在服务器上。很多 Delphi 开发者只盯着客户端控件服务器上扔一个裸 zip 就完事结果用户下载一半断网、版本号覆盖错、32 位和 64 位包混发最后全部变成升级失败。这一章把服务端文件约定和发版动作讲清楚。4.1 服务器目录约定版本清单、更新包、存放规则服务器上单独建一个目录比如 /soft/erp/目录下放三样东西version.ini、当前版本的完整更新包、以及一个 last_update.txt 记录发布时间方便出问题时回溯。普通 HTTP 服务就够Nginx 配成静态目录客户端直接访问固定 URL。约定一version.ini 永远表示“当前发布的最新版本”内容覆盖不保留历史版本记录。约定二更新包文件名和版本号强绑定比如 erp_1.0.13.zip避免下载到旧包。约定三目录本身禁止列出文件但固定文件名必须能直接访问避免爬虫或者误列。我用的 version.ini 模板[Version] Current1.0.13 Packageerp_1.0.13.zip Size24819200 MD53a40b2c9f67d8e1a5c0b2d3e4f5a6b7c MinVersion1.0.9 Force0字段逻辑Current 是服务器最新版本号Package 是本次更新包文件名Size 是包大小客户端下载前可用于磁盘空间判断MD5 做完整性校验下载完先算一遍再替换MinVersion 表示低于这个版本的客户端必须更新Force1 时客户端不允许跳过。这套字段是我从多个项目里沉淀出来的内容少但能覆盖弹窗询问、强制升级、损坏重下三种主要场景。4.2 生成更新包与完整性校验哈希、签名与发版顺序更新包里放什么最常见做法是把新 exe、运行所需 dll、以及更新后的配置文件模板打进全量 zip。配置需要注意如果用户本地已经改过连接串或界面选项打包时不要覆盖用户配置要么不打包配置要么在客户端做配置文件合并。我一般只打包 exe 和 dll配置文件由程序首次启动时自动补齐。打完包后必须算哈希写进 version.ini。手动算容易手滑我一直用 PowerShell 一条命令# 计算更新包哈希输出后填入 version.ini 的 MD5 字段 Get-FileHash -Path C:\build\erp_1.0.13.zip -Algorithm MD5 | Select-Object Hash逻辑说明Get-FileHash 读取更新包文件-Algorithm MD5 指定哈希算法Select-Object Hash 只输出哈希值。如果团队安全要求更高可以把 MD5 换成 SHA256version.ini 里的字段同步改名客户端校验逻辑也要对应调整。哈希解决的是“下载损坏”“文件名对不上”这类问题防不了恶意篡改真正要防篡改必须给 exe 数字签名并让更新服务走 HTTPS。给 exe 签名我一般用 signtool命令如下signtool sign /f mycert.pfx /p 123456 /t http://timestamp.example.com /fd SHA256 erp_1.0.13.exe这里 /f 指定证书文件/p 是证书密码/t 是时间戳服务器地址/fd SHA256 指定摘要算法。没签名的程序在 Win10/11 上 SmartScreen 会提示“未知发布者”不少用户直接不敢点所以签名不是可选项而是发布前必做项。4.3 Win32 与 Win64 双版本发布的路径陷阱很多 Delphi 老项目长期只发 Win32 包因为 64 位 Windows 也能跑 32 位 exe。但 Delphi 12.3 默认同时产出 Win64 构建服务器上如果只开一个“最新版”目录两套架构的包混在一起64 位用户下到 32 位包功能看起来正常某些驱动和内存占用场景却会有微妙问题最难排查。我的做法是服务器分两个子目录/erp/x86/ 和 /erp/x64/各自维护一份 version.ini。客户端在创建时按编译目标指定自己的更新目录{$IFDEF WIN64} AutoUpgrader1.FilesURL : http://update.example.com/erp/x64/; {$ELSE} AutoUpgrader1.FilesURL : http://update.example.com/erp/x86/; {$ENDIF}逻辑说明用编译条件判断当前 exe 是 64 位还是 32 位然后指向不同的更新目录。这样两个平台的发布进度互不干扰服务端也能并行验证。参数说明这条逻辑必须在主程序任何升级请求之前执行否则首次安装的客户端拿不到正确地址。另外更新包命名建议纯 ASCII中文文件名在部分 Windows 服务器和客户端编码组合下会下载失败erp_1.0.13.zip 这种最省心。5. 排查与避坑AutoUpgrader Pro v5.02 在 Delphi 12.3 下的五类翻车现场自动升级控件的坑很多不是功能没有而是边界条件没满足。这一章整理我真实踩过、或帮同事排查过的五类现象每条按“现象 → 原因 → 解决”写照着对号入座。5.1 运行提示找不到 dcuLibrary path 的 Win64 位漏配现象IDE 编译工程不报错运行到使用 AutoUpgrader 的单元时提示 Cannot find unit AutoUpgraderPro.dcu或者能编译但在 Tool Palette 里看不到控件。原因Delphi 12.3 的 Library path 按平台分离你很可能只在 32-bit Windows 下加了预编译 dcu 目录Win64 工程找不到 64 位版本。IDE 编译时对已安装包的搜索有容错运行时却需要 dcu 或 bpl 真实存在。解决打开 Tools Options Library把 Platform 下拉框切到 64-bit Windows再把 lib\d12\win64 加进搜索路径。如果包只有源码直接把 Source 目录加进去让编译器现场生成 dcu。加完重开工程确认 Tool Palette 里显示正常再继续。5.2 升级时提示文件被占用替换时机不对现象用户点更新下载进度走完替换 exe 时弹“无法写入文件另一个程序正在使用”升级失败。原因替换动作发生时主程序进程还没退出Windows 不允许覆盖正在运行的 exe。部分自动升级控件内置了重启替换逻辑但如果你用的是源码版并自己管理替换很容易漏掉退出时序。解决让控件先退出主程序再替换。如果控件没有内置该流程更通用做法是下载完成后启动一个独立小工具 UpdateLauncher.exe由它等待主进程退出后再执行复制。底层用 Windows API 的 MoveFileEx 也能做到MoveFileEx(PChar(OldExe), PChar(NewExe), MOVEFILE_REPLACE_EXISTING or MOVEFILE_WRITE_THROUGH);逻辑说明MoveFileEx 在系统重启时补齐剩余的替换动作MOVEFILE_REPLACE_EXISTING 允许覆盖已存在文件MOVEFILE_WRITE_THROUGH 确保写盘完成后再返回。这个方案适合极端的“文件被占死”场景但会拖到下次开机才生效体验不好我更喜欢独立启动器方案。5.3 版本号回跳字符串比较让 v5.02 大于 v5.10现象用户机器上明明装的是 v5.02服务器发的是 v5.10升级却认为本地版本更新不弹更新提示。反过来 v5.02 和 v5.10 比较时控件把 v5.02 判定为更新版本。原因控件默许版本号按字符串逐位比较。“5.02”和“5.10”逐位比第 3 位 0 小于 1但是第 4 位 2 大于 0最终结果取决于具体位数。这种比较方式对“v5.10”这种带前导零、宽度不等的版本号必出问题。解决版本号统一成四位等宽数字比如 0502、0510或者把版本拆成数组逐段转整数比较。客户端如果已经有“5.02”这种老数据在读取后先过滤掉点号再补零不要拿原始字符串直接比。我现在所有项目的版本号都按 Major10000 Minor100 Build 转成整数存元数据从源头杜绝这个问题。5.4 替换后的 exe 被杀软隔离现象升级完成后新 exe 消失或者杀毒软件弹“已隔离”。重复多次后用户觉得升级有病毒直接不再点更新。原因未签名的 exe 自我替换、下载文件落在 %TEMP% 临时目录、下载源又是内网裸 IP这些行为叠加起来很容易被启发式引擎判定为恶意程序。解决给 exe 数字签名并勾选时间戳更新包下载到程序目录下的 updates 子目录而不是 %TEMP%发布前把完整安装包上传到在线查毒平台预检。内网自建更新服务时把更新服务器域名加入终端白名单。签名做完自己验证一次signtool verify /pa erp_1.0.13.exe逻辑说明/pa 表示验证签名是否有效且可信。如果企业环境有专用证书链还要把根证书部署到客户端机器否则客户端不认签发者。签名不是形式是自动升级能不能被信任的底线。5.5 升级窗口在 4K 屏上模糊或错位现象升级提示窗口在用户高分屏上文字模糊、按钮拉伸低分辨率机器上正常。原因控件自绘界面没有适配 Per-Monitor DPI V2。Delphi 12.3 默认在 manifest 里声明了 DPI 感知老控件按自身逻辑绘制遇到多显示器不同缩放率就错位。解决把程序 manifest 的 dpiAwareness 调整到 System 或 PerMonitorV1牺牲一点高分屏清晰度换取控件界面稳定更彻底的做法是升级界面自绘控件只负责下载和替换界面用自己的 Form 呈现。我的习惯是后者——反正自动升级窗口只有那几秒自绘还容易统一风格不受控件版本约束回报比更高。6. 半小时搭出可验证的升级闭环回滚、日志与自动化检查升级功能写完不验证等于没写。验证方法不需要复杂环境本地起一个静态文件服务目录结构照第 4 章的约定放好 version.ini 和更新包。客户端装旧版本把 version.ini 的 Current 改大观察三步弹不弹更新提示、下载完替换没、重启后本地版本文件是否变成新版本。三步全对闭环才算通。回滚习惯我现在坚持做升级前把当前 exe 复制到 backup 目录新版本替换后用户反馈异常能快速还原。多数控件不会主动备份旧文件这步自己写在 OnUpdateDownloaded 里代码不超过十行关键时刻是后悔药。日志要记到固定位置我用 %LOCALAPPDATA%\YourApp\updater.log内容至少包含远端版本号、下载字节数、MD5 核对结果、替换是否成功。之后用户报问题第一件事就是拉 updater.log而不是远程截屏。自动化检查我放在 CI 或定时任务里定期拉取服务器上的 version.ini和数据库里记录的“已发布版本”比对不一致就告警。这能避免发版流程只发不验发布新包却忘更新版本文件的低级事故。现在回顾我在多个项目里最深的教训就是版本号比较规则和签名这两件事。版本号吃过亏之后我在所有工程里统一了整数比较签名这步再急也等 signtool verify 通过才发。每次发版我都要求自己先写 version.ini再打 zip再签名最后在测试机双击旧版程序跑一遍完整升级。流程走得多了升级事故自然少了大半。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?