新闻详情

新闻详情

首页 / 资讯中心 / 详情

Inno Setup实战:从exe到专业安装包的完整打包指南

发布时间:2026/9/29 19:46:16来源:尧图网络
Inno Setup实战:从exe到专业安装包的完整打包指南
先说个我见过太多次的场景一个程序开发完了交付方式还是“给你一个压缩包里面一堆 dll、一个 exe、一份 readme.txt”用户双击 exe 能跑就万事大吉跑不起来就开始漫长的问题排查。做为一个经常用 Inno Setup 打包 exe 文件为安装包程序的人我建议你尽早把“双击安装、自动装依赖、桌面快捷方式、卸载干净”这一套流程跑通。这篇就专门讲清楚怎么把散落的 exe 文件做成一个像样的安装包程序以及在这个过程中你会踩到的各种坑。1. 为什么最终选了 Inno Setup1.1 它到底是干什么的先给第一次接触的朋友一个准确认知。Inno Setup 是一个免费开源的 Windows 安装程序制作工具它做的事情可以概括成一句话把若干源文件、配置信息、快捷方式规则、注册表写入项通过一套脚本描述最后编译成一个独立的 setup.exe。用户拿到这个 setup.exe运行之后会看到一个安装向导一路 Next 就能把软件装好之后还可以通过系统自带的“卸载程序”把它完整卸掉。很多人会把“打包 exe”和“压缩 exe”搞混。压缩包只是把文件体积变小解压后还是原来的散文件而安装包程序额外承担了“安装逻辑”——装到哪个目录、写哪些注册表、建哪些快捷方式、是不是要开机启动、安装结束后要不要立即运行。这些逻辑如果靠压缩包手动处理就变成用户自己做的事了。Inno Setup 的价值就是把这一堆琐碎事情用脚本固化成产物。我选它还有一个很实际的原因它的脚本是纯文本格式可以直接放进版本库管理。每次发版改版本号、改输出文件名我只要改脚本里的个别字段然后扔进构建流水线让命令行自动编译几秒钟出一个安装包。相比某些需要手动点击界面的图形化打包工具这种方式在持续交付场景里太省心了。1.2 和主流打包工具的横向对比市面上做 Windows 安装包的方案不少简单列一下我实际见过的主流选项方便你判断为什么 Inno Setup 是大多数人最划算的起点工具定位与授权脚本或界面适合场景Inno Setup免费开源脚本驱动带可视化向导中小型软件、工具类 exe、Python/Qt 程序打包NSIS免费开源脚本驱动插件生态丰富需要高度定制安装界面的场景Advanced Installer有免费版专业功能收费图形界面为主企业内部软件包、MSI 需求InstallShield商业授权图形界面与自动化并存大型企业级产品、复杂安装规则如果你只是想把“exe 依赖文件 图标 安装/卸载”做好Inno Setup 完全够用而且它默认生成的安装包文件体积极小启动速度快支持 Unicode 中文路径对 32 位和 64 位程序都有良好支持。NSIS 同样免费但它的脚本方言和插件管理我个人觉得上手门槛更高如果只是普通交付没必要一开始就碰它。Advanced Installer 和 InstallShield 在有企业部署、MSI 分发包需求时更合适但普通开发者临时做安装包这两者的学习成本和授权成本都偏高。另外一个偏向直觉但很重要的一点Inno Setup 的脚本能精确控制“装完后用户看到什么、系统里被改了哪些地方”。我甚至见过有人只用 Inno Setup 来做一个几十 GB 游戏资源的“安装引导器”把资源文件分包压缩、分卷输出照样管得住。它的下限很低上限也不低。2. 先跑通一个最小打包流程2.1 下载与安装工具去 Inno Setup 官网下载 6.x 版本安装时一路默认即可。装完之后你会看到一个 “Inno Setup Compiler” 的编译环境这就是我们写脚本、编译安装包的入口。有一点很容易被忽略安装目录下自带Languages目录里面有多种语言翻译文件。你做中文安装包时界面默认会识别系统语言但如果想要强制中文或做多语言切换后续需要在脚本里显式指定语言文件。我的习惯是装完之后先飞快地确认一下命令行工具是否可用。Inno Setup 安装目录下的ISCC.exe就是命令行编译器后面做自动构建时会用到它。如果你想要把打包过程集成到 Jenkins、GitLab CI 里这就是关键入口。2.2 用向导生成第一版脚本Inno Setup 自带一个脚本向导菜单位置是 File - New或者直接 CtrlN。打开向导后会依次问你几个问题应用名称、版本号、发布者、默认安装目录、主执行文件、需要额外加入的文件和文件夹、是否创建快捷方式、默认安装语言。你按实际项目填完向导会自动生成一份可用的.iss脚本文件。这里我要说清楚一个体验上的关键点向导生成的脚本只是一个骨架距离生产级安装包还有距离。它的作用是让你先跑通“编辑脚本 - 编译 - 生成 setup.exe”这条完整链路建立起对脚本结构和生成结果的直觉而不是让你以后每次都靠点向导。2.3 动手改脚本把exe塞进去向导生成之后我们手工打开脚本文件通常至少会看到这样几个部分[Setup] AppId{{8A7E2F5C-4D3B-4C5A-9B0E-1C2D3E4F5A6B} AppNameMyApp AppVersion1.0.0 DefaultDirName{autopf}\MyApp PrivilegesRequiredadmin OutputDir.\output OutputBaseFilenameMyApp-Setup Compressionlzma2 SolidCompressionyes [Files] Source: dist\MyApp\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs [Icons] Name: {autoprograms}\MyApp; Filename: {app}\MyApp.exe Name: {autodesktop}\MyApp; Filename: {app}\MyApp.exe; Tasks: desktopicon [Tasks] Name: desktopicon; Description: 创建桌面快捷方式; GroupDescription: 附加图标: [Run] Filename: {app}\MyApp.exe; Description: 运行 MyApp; Flags: nowait postinstall skipifsilent逐行解释下最关键的两段。[Setup]段是整个安装包的“身份证”AppId是安装程序的唯一标识我建议每次新建工程都生成一个新的 GUID它直接被写入系统的卸载注册表卸载时会根据它找到你的程序DefaultDirName决定默认安装位置我用{autopf}这个常量它能根据当前安装的是 32 位还是 64 位程序自动选择 Program Files 或 Program Files (x86)PrivilegesRequiredadmin表示安装时需要管理员权限适合要写系统盘、注册表、服务类的软件如果是纯用户级工具也可以改成lowest避免弹出 UAC。再看[Files]段这行短短代码是打包的核心Source: dist\MyApp\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs意思是把dist\MyApp文件夹下的所有东西包括子目录里的文件完整复制到安装目录{app}下。recursesubdirs表示递归子目录createallsubdirs表示一并创建对应的子目录结构ignoreversion表示目标目录里已存在同名文件时直接覆盖而不是比较版本号。像 Python 打包工具生成的 exe 往往带有一大堆辅助文件这种“整个目录递归打包”的方式是最省事的。2.4 编译与测试回路脚本保存后按 F9 或点击编译按钮Inno Setup 就会在脚本同目录下生成output\MyApp-Setup.exe。第一次编译大概率不会一次过最常见的问题是路径写错、Source 路径找不到文件或者权限不够导致输出目录无法写入。编译器报错信息里会告诉你文件名和行号大多数时候跟着改就行。编译成功不等于安装包就是好的。我强烈建议你在至少两台不同环境测试一台全新虚拟机、一台自己常用的开发机。分别验证这些点安装向导是否完整走完安装后的程序能不能正常启动快捷方式有没有生成卸载之后目录、注册表、快捷方式是否都清理干净。宁可多花十分钟测试也不要发一个“装完就报 DLL 缺失”的包给用户。测试时有个特别好用的参数手动运行安装包时加上/LOGC:\install.log安装程序会把每一步操作写进日志文件。用户反馈“装不上”的时候让对方把这份日志发回来往往比反复问话更能定位问题。3. 把安装包做专业的脚本细节3.1 [Setup]段产品的“身份证”字段[Setup]段有不少字段直接影响安装体验我把常用的参数收集成一张表照着填不会乱参数作用建议AppId安装包唯一标识写入卸载注册表每个产品固定不变避免后期无法卸载AppName显示在安装向导、卸载列表里的名称用产品显示名不要用文件名AppVersion版本号保持和程序内部版本一致DefaultDirName默认安装目录用{autopf}或{userpf}区分全局/用户级安装OutputBaseFilename生成的安装包文件名建议包含版本号例如MyApp-1.0.0-Setup.exeCompression压缩格式默认lzma2压缩率最高对体积要求高时保持默认SolidCompression是否整体压缩设为yes能进一步缩小体积UninstallDisplayIcon卸载列表中的图标指向{app}\MyApp.exe即可这里有个非常容易被忽略的坑AppId一旦发布出去就不要随便更换。卸载程序在系统里的注册表键名基于AppId生成如果新版本换了一个 GUID用户升级后系统里会同时出现新旧两个卸载条目旧版本反而卸不干净。改版号、改名都没问题唯独这个 ID 要认准。还有DefaultDirName的选择策略。如果你的程序需要写 Program Files、要装驱动、要提供服务就用{autopf}加管理员权限如果只是一个普通用户态工具我更推荐装到用户目录例如DefaultDirName{userpf}\MyApp PrivilegesRequiredlowest这样安装不需要 UAC 提权对小工具非常友好也能避免“用户没管理员权限就装不上”的尴尬。3.2 [Files]段目录结构和特殊常量[Files]段负责把源文件复制到目标位置它的核心表达式是Source从哪里来和DestDir装到哪里去。除了{app}还有几个常用目标常量{sys}系统目录对应 64 位系统里的 System32放驱动的 dll、系统组件时用{win}Windows 目录很少直接往里写东西{userappdata}当前用户的 AppData\Roaming放用户配置和缓存{commonappdata}所有用户的 AppData\Roaming放公共数据{tmp}安装过程中的临时目录安装结束自动清理我实际处理 Python 或 Qt 生成的一堆文件时最常用的就是整目录递归Source: dist\MyApp\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs注意Source路径里的*星号它代表“该目录下所有内容”配合recursesubdirs才能把子目录也带进来。如果你只想打单个文件写法是Source: build\release\MyApp.exe; DestDir: {app}; Flags: ignoreversion还有一个很容易踩的细节脚本里的Source路径是相对脚本文件所在目录解析的不是相对 exe 所在目录。我见过不少人把.iss放在别处导致编译时报找不到文件。保险做法是让脚本文件固定在项目根目录源文件路径按它来写或者在脚本开头加上一行注释提醒自己。有些不希望被用户直接修改的配置文件可以考虑放到 AppData。这个在后续处理 Python 程序的可变配置时尤其实用。3.3 快捷方式、卸载信息和安装后动作快捷方式由[Icons]段控制。最典型的需求是安装完成后给桌面和开始菜单各建一个快捷方式。桌面快捷方式默认不一定要建因为不是所有用户都喜欢所以我习惯把它挂到[Tasks]组里给用户一个勾选项。[Tasks] Name: desktopicon; Description: 创建桌面快捷方式; GroupDescription: 附加图标:; Flags: unchecked [Icons] Name: {autoprograms}\MyApp; Filename: {app}\MyApp.exe Name: {autodesktop}\MyApp; Filename: {app}\MyApp.exe; Tasks: desktopicon这是一个非常常见的组合[Tasks]定义用户可勾选的任务项[Icons]里的Tasks: desktopicon表示该快捷方式只在用户勾选 “desktopicon” 任务时才创建。Flags: unchecked让桌面快捷方式默认不勾选这对追求干净的用户体验很重要。[Run]段控制安装结束后要不要执行某些程序。比如装完驱动类软件后立刻运行主程序或者调用系统工具注册组件[Run] Filename: {app}\MyApp.exe; Description: 运行 MyApp; Flags: nowait postinstall skipifsilentpostinstall表示这行命令在安装向导完成页出现用户可以通过勾选框决定是否执行nowait表示不等待程序退出skipifsilent表示静默安装时不执行。卸载信息这块其实 Inno Setup 默认就生成了卸载程序叫unins000.exe和安装目录放在一起系统卸载列表里的条目会自动注册。你只需要注意别把unins000.*文件打包进[Files]——很多时候用户会反手把整个安装目录压缩备份其中就包含了卸载程序反而导致配置残留。3.4 用[Code]段处理更复杂的场景很多教程写到[Run]就结束了但实际交付时你会发现有些需求靠参数解决不了需要在安装过程中写自定义逻辑。Inno Setup 内置一个 Pascal 脚本引擎[Code]段就是写这些逻辑的地方。最典型的例子是安装前检查目标程序是否正在运行。如果程序没退出就覆盖安装大概率文件被占用导致安装失败。下面这段代码实现了“检测到进程在跑就提示用户关闭”[Code] function IsAppRunning(const ExeName: string): Boolean; var FSWbemLocator: Variant; FWMIService: Variant; FWbemObjectSet: Variant; begin Result : False; FSWbemLocator : CreateOleObject(WBEMScripting.SWBEMLocator); FWMIService : FSWbemLocator.ConnectServer(, root\CIMV2); FWbemObjectSet : FWMIService.ExecQuery( Format(SELECT Name FROM Win32_Process WHERE Name%s, [ExeName])); Result : not VarIsNull(FWbemObjectSet) and (FWbemObjectSet.Count 0); end; function InitializeSetup(): Boolean; begin if IsAppRunning(MyApp.exe) then begin MsgBox(请先关闭 MyApp 再进行安装, mbError, MB_OK); Result : False; end else Result : True; end;这段只是抛砖引玉。你还可以用[Code]做自定义安装选项页、按条件写注册表、检测系统是否有 .NET 或 VC 运行库甚至实现“安装完成前必须连网校验许可证”。对于普通交付用到InitializeSetup和NeedRestart这两个函数的概率最高。后者用来告诉系统安装完后是否需要重启function NeedRestart(): Boolean; begin Result : false; // 如果安装过程中替换了正在使用的系统文件这里可以返回 True end;我的经验是能用[Setup]和分区参数解决的不要急着写[Code]。脚本越短越容易维护但当你确实需要“在安装时做判断”的那一刻[Code]就是救命的工具。4. 不同来源的exe怎么打包4.1 Python打包的exe先PyInstaller再Inno Setup现在 Python 转 exe 已经是很多人发布小工具的主要方式。流程一般是用 PyInstaller 把 Python 脚本转换成一个独立 exe再用 Inno Setup 把它变成安装包。这条路我走得很熟但有三个关键提示。第一先决定 PyInstaller 用哪种产物。PyInstaller 可以生成--onefile单文件模式也可以生成--onedir目录模式。--onefile的好处是只有单个 exe但坏处是启动时会先自解压到临时目录杀毒软件误报率相对高启动速度也慢--onedir会生成一个包含 exe 和一堆依赖 dll、pyc 资源文件的目录程序启动快、误报率低正好适合后续用 Inno Setup 打包整个目录。所以我实际发布时几乎总是用--onedir然后配合 Inno Setup 的递归目录打包。第二在干净环境里做 PyInstaller 构建。建议在虚拟环境里只安装程序真正用到的依赖再做构建否则 PyInstaller 会把你项目里实际上没用到、但环境中存在的库一并塞进来最终安装包体积失控。这个坑我踩过不止一次明明一个读取 Excel 的小工具打包出来一两百 MB一查全是无用的包。第三区分 GUI 和命令行程序。如果你的 Python 程序有图形界面PyInstaller 构建时记得加--noconsole参数否则用户运行时还会弹出一个黑色的控制台窗口很掉档次。构建命令参考pyinstaller --noconfirm --clean --noconsole --onedir main.py之后dist\main文件夹里就是完整产物。然后 Inno Setup 脚本就把dist\main整个递归打包即可。如果程序运行后需要读写配置文件你可以在 [Files] 段把它复制到{userappdata}\YourApp避免把配置文件留在 Program Files 里导致权限问题。4.2 Qt程序先补依赖再打包Qt 程序的安装包制作过程有一套常见组合拳先拿 Qt 自带部署工具补依赖再用 Inno Setup 封装。因为 Qt 程序编译出来的 exe 通常不能直接拷到别的机器运行还缺一大堆 Qt 运行库、平台插件、样式插件。我用的是 Qt 自带的windeployqt.exe。构建完程序后打开 Qt 对应的命令行环境在 exe 目录下执行windeployqt MyApp.exe --release它会自动分析 MyApp.exe 依赖的 Qt 模块把 Qt5Core.dll、Qt5Gui.dll、platforms 目录、styles 目录、imageformats 目录等一并复制到 exe 旁边。这一步做完后exe 同目录下会多出不少 dll 和子目录这些就是 Inno Setup 要打包的内容。使用windeployqt时有几个容易踩的坑版本和编译套件要匹配。MSVC 版 Qt 就必须用 Visual Studio 的开发者命令行环境MinGW 版 Qt 则要确保 mingw 的相关 dll 在 PATH 中。用错环境部署出来的依赖可能引入一堆 MSVCP 运行库问题。部署完成后一定要自己先双击 exe 跑一遍。如果有的模块没复制全程序启动后会立即报错这时候补拷贝比等安装包做出来再排查省事得多。如果程序用了第三方 C 库比如 OpenCV、PCLwindeployqt不会帮你处理这些依赖需要手工把对应的 dll 拷进目录。依赖补全后Inno Setup 这边就是标准玩法[Files] Source: build\MyApp\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs如果你做的是安装时选“只给当前用户安装”的便携模式还可以用{userpf}作为安装目录避免用户没有管理员权限装不进去。4.3 驱动类exe不一定非要“安装”直接提取inf这部分对应的是很多人搜过的问题如何从 exe 形式的驱动文件里提取 inf 文件。先说结论很多驱动安装包本质是一个自解压程序运行时会把驱动文件释放到临时目录再调用驱动程序安装组件去读取 inf 并安装硬件驱动。这种情况下你完全不需要真的运行它的安装向导也可以把核心文件提取出来。一个常见的做法是使用 7-Zip。把 7-Zip 安装后直接对驱动 exe 右键选择“打开压缩包”注意不是“解压到当前文件夹”而是用压缩包浏览的方式打开。很多自解压驱动文件在这种方式下会被解析成普通压缩包里面的目录结构会出现在窗口里。找到 inf、sys、cat 等文件后单独抽出需要的部分。如果不方便用 7-Zip还可以先用/e或/a这类参数把自解压包静止展开到指定目录不过这要看具体驱动包采用的封装工具通用性不如 7-Zip。更稳妥的思路是运行一次驱动安装程序然后立刻到%TEMP%目录里找它释放出来的文件夹。这个方法不优雅但对付顽固包基本有效。这里必须多说一句驱动文件一定要从官方源获取。提取只是手段目的要么是离线部署、要么是排查某个驱动是否包含特定组件而不是让你去修改或绕过任何签名校验。inf 和 sys 文件如果来源不对后患极大不要以身试险。提取出 inf 后如果你确实想手动安装可以在设备管理器里选择“更新驱动程序 - 浏览我的电脑以查找驱动程序”指向提取目录即可。也可以右键 inf 文件选择“安装”系统会自动触发驱动安装流程。5. 常见问题与排查思路5.1 文件被占用、权限不足“文件正在被另一个进程使用无法覆盖”是我见过最多的安装失败原因。用户机器上程序已经运行安装时却试图覆盖 exe 或 dllWindows 会直接拒绝写入。对策分两层一层是写[Code]检测进程另一层是给安装包加上“安装前自动关闭进程”的选项。比如[InstallDelete] Type: files; Name: {app}\MyApp.exe[InstallDelete]可以解决“旧文件存在但不可覆盖”的部分场景但根子上还是要配合进程检测。在程序自身支持命令行的前提下我偶尔也会在[Run]安装前执行taskkill不过这个方案对用户不友好能不用尽量不用。权限不足的另一个来源是安装目录选到了需要管理员权限的位置。之前提过的PrivilegesRequired和DefaultDirName要一起考虑。普通工具装到 Program Files 又不想提权必然冲突。要么放弃 Program Files要么接受 UAC 弹窗没有第三种选择。5.2 安装包被杀毒软件拦截这是 Inno Setup 用户最头疼的问题尤其是 Python 打包出来的 exe。PyInstaller 生成的程序本质上是自解压型可执行文件很多杀毒引擎会对它产生误报。Inno Setup 生成的 setup.exe 又经常被 SmartScreen 提示“未知发布者”。我的处理建议按优先级排使用代码签名证书。哪怕只是 OV 证书签名后 SmartScreen 的警告就会从“未知发布者”变成正常提示。免费的自签名证书没有意义用户机器不会信任。确保安装包不包含无意义的高压壳特征。PyInstaller 的--onefile模式更容易触发误报改用--onedir再配合 Inno Setup 打包误报率明显下降。发布前自己上传到 VirusTotal 做一次扫描。如果多家引擎报毒先检查程序本身是否有异常行为而不是直接给杀毒软件扣“误报”的帽子。5.3 路径、中文和64位系统坑Inno Setup 6.x 默认支持 Unicode中文路径和中文安装目录没有问题前提是脚本文件本身保存为 UTF-8 带 BOM 或 ANSI 编码。如果脚本文件是 GB2312 编码且里面写了中文编译时有时会出现乱码或找不到语言文件的问题。64 位系统还有一个文件重定向问题。32 位安装程序往{sys}写文件时系统会把它重定向到 SysWOW64导致文件写到了和预期不同的地方。如果你的程序是 64 位安装包编译前要确认脚本里的ArchitecturesInstallIn64BitMode设置正确ArchitecturesInstallIn64BitModex64compatible ArchitecturesAllowedx64compatible这两行的含义是允许在 64 位系统上安装且安装进程以 64 位模式运行{sys}指向真正的 System32。如果不加32 位安装进程访问{sys}时就会被重定向到 SysWOW64驱动类的文件装错位置是灾难性的。5.4 静默安装与日志定位问题企业部署或自动化测试时经常需要静默安装。Inno Setup 支持命令行参数直接静默安装MyApp-Setup.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP/VERYSILENT表示安装过程不显示界面/SUPPRESSMSGBOXES表示抑制所有弹窗/NORESTART表示即使提示需要重启也不触发/SP表示跳过“这个程序将安装在你的电脑上”的确认页。用户装完反馈“没反应”“失败”这时候最有效的排查手段是让用户帮忙跑一次日志MyApp-Setup.exe /VERYSILENT /LOGC:\install.log这份日志详细记录了安装包每一步的解压、文件复制、注册表操作、快捷方式创建。我见过太多人遇到安装失败靠猜其实日志里写得明明白白是哪一个文件复制失败。学会让用户提供/LOG日志排查效率能提高一个量级。5.5 实测过程速查表症状常见原因排查和解决安装到一半报缺少 dll源文件未打包完整检查[Files]Source 目录是否包含所有依赖Qt 程序确认 windeployqt 执行过快捷方式没有生成[Icons]的 Tasks 条件和用户勾选不匹配检查[Tasks]定义和[Icons]中的 Tasks 属性安装后程序无法启动依赖缺失、运行库版本不对、读取配置路径错误先解压安装目录单独运行 exe 定位再看 Windows 事件日志卸载之后还有残留目录配置和数据文件写在{app}以外的位置用[UninstallDelete]删除用户数据目录或注册表删除对应键值静默安装失败无提示参数写错、安装包被安全软件拦截加/LOG跑一次同时检查安装包的数字签名6. 一些踩坑之后的体会最后聊点没写在官方文档里的经验。我第一次用 Inno Setup 是在一个发布 Qt 桌面程序的项目里当时不懂windeployqt的重要性直接拿编译后的裸 exe 去打包结果用户装完启动就闪退后来才发现 platforms 目录根本没打进去连排了一天。后来我把流程固定成源码编译 - 依赖部署 - 本地自测 - Inno Setup 打包 - 干净虚拟机安装验证。这套顺序一直沿用到现在几乎没有再翻过车。另一个体会是关于脚本习惯的。我喜欢把版本号单独定义成脚本变量所有输出文件、快捷方式名称都引用它#define MyAppVersion 1.0.0 #define MyAppName MyApp [Setup] AppName{#MyAppName} AppVersion{#MyAppVersion} OutputBaseFilename{#MyAppName}-{#MyAppVersion}-Setup这样每次发版只需要改一行输出文件名、安装包内版本信息、注册表显示全部同步更新。这个小习惯帮我避免了很多次“文件名版本号和程序内部版本号不一致”的低级事故。如果你只是偶尔打包一次跟着上面最小脚本跑通就够如果你们团队天天发版我强烈建议把 Inno Setup 的ISCC.exe编译命令接进 CI。脚本里只保留版本变量提升处让构建机器人自动填版本号然后产出安装包上传到内部发布平台。你会发现安装包这件事一旦进入自动化轨道就再也没有人肉点下一路的烦恼了。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

AI资讯日报系统搭建实战:信源分级、去重排序与自动摘要 2026/9/29 20:36:53

AI资讯日报系统搭建实战:信源分级、去重排序与自动摘要

1. 当“日报”变成一种技术活:AI资讯聚合的真实门槛每天早上七点,我的手机闹钟还没响,Slack 里的机器人已经推了三条链接过来。点开一看,两条是三天前的旧闻,一条是某公司融资通稿的二次转载。这种体验相信不少做 AI 方…

阅读更多 →
VSCode + RemoteSSH 连虚拟机 Linux:TaoToken 统一 Key 的 settings.json 配置骨架 2026/9/29 20:36:53

VSCode + RemoteSSH 连虚拟机 Linux:TaoToken 统一 Key 的 settings.json 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
告别手动点上传:miniprogram-ci 把小程序提审打包成一条命令 2026/9/29 20:36:53

告别手动点上传:miniprogram-ci 把小程序提审打包成一条命令

告别手动点上传:miniprogram-ci 把小程序提审打包成一条命令 适用读者:负责微信小程序日常迭代与发版的前端工程师、维护小程序 CI/CD 流水线的 DevOps 同学。假设你已经能独立跑通微信开发者工具的预览与上传,对 Node.js 脚本和 Git 打 tag …

阅读更多 →
DeepSeek V3.2 正式版 Agent 能力实测:用 TaoToken 统一 Key 跑通思考推理链路 2026/9/29 20:36:46

DeepSeek V3.2 正式版 Agent 能力实测:用 TaoToken 统一 Key 跑通思考推理链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
技术革命与全球浩劫的结构性失衡机制研究——基于两次世界大战、核威慑时代与人工智能时代的全周期推演 2026/9/29 20:36:46

技术革命与全球浩劫的结构性失衡机制研究——基于两次世界大战、核威慑时代与人工智能时代的全周期推演

技术革命与全球浩劫的结构性失衡机制研究——基于两次世界大战、核威慑时代与人工智能时代的全周期推演摘要传统国际关系与历史研究对两次世界大战的阐释,长期固化于帝国主义发展不平衡、殖民利益争夺、凡尔赛体系缺陷、经济危机冲击等表层叙事,未能触及…

阅读更多 →
L2 OpenCompass 评测书生大模型实践:用 TaoToken 统一 Key 打通 VLMEvalKit 配置 2026/9/29 20:36:46

L2 OpenCompass 评测书生大模型实践:用 TaoToken 统一 Key 打通 VLMEvalKit 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉