恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
SoundSwitch 发布工具链详解:从构建环境到 Release 发布的全流程指南
首页
资讯中心
/
SoundSwitch 发布工具链详解:从构建环境到 Release 发布的全流程指南
SoundSwitch 发布工具链详解:从构建环境到 Release 发布的全流程指南
发布时间:2026/10/4 1:43:17
桌面应用【免费下载链接】SoundSwitchC# application to switch default playing device. Download: https://soundswitch.aaflalo.me/项目地址https://gitcode.com/gh_mirrors/so/SoundSwitch点击查看免费下载本文聚焦 SoundSwitch 仓库tools/目录下的 PowerShell 7 发布工具链逐一拆解环境准备Install-BuildTools.ps1、安装包编译与签名Build-Installer.ps1 / Sign-Binary.ps1、完整发布编排Publish-Release.ps1、Markdown 文档转 HTMLmarkdown_to_html.py与夜间构建上传upload_nightly_r2.py五个环节。读完本文你将掌握 SoundSwitch 从源码/草稿 Release 一路走到正式发布、再到夜间构建分发的完整自动化路径并理解每一条命令背后的源码级实现细节。工具链概览与运行前提tools/目录是 SoundSwitch 发布流程的核心所在目录入口说明见 tools/README.md其中包含以下工具工具脚本职责Install-BuildTools.ps1在全新 Windows 11 机器上一键安装全部构建与签名工具Sign-Binary.ps1用 signtool 对可执行文件做 SHA-256 签名与 RFC 3161 时间戳Build-Installer.ps1编译并签名 Inno Setup 安装包不负责源码构建与发布Publish-Release.ps1完整发布编排产物准备 → 文档生成 → 安装包 → 上传草稿 Release → 发布markdown_to_html.py将 Markdown 转为独立 HTML 文档替代旧的markdown-htmlnpm 包upload_nightly_r2.py上传夜间构建压缩包到 Cloudflare R2 并通知 Discordvswhere.exe定位 Visual Studio 安装位置发布流程辅助运行前提硬性要求所有 PowerShell 脚本都要求PowerShell 7Windows 11 自带与 Windows PowerShell 5.1 不兼容。脚本开头均有#Requires -Version 7.0指令参见 Install-BuildTools.ps1 第 34 行在 5.1 下运行会直接报错。Python 脚本则要求 Python 3 及markdown包。一、环境准备Install-BuildTools.ps1 一键安装Install-BuildTools.ps1 面向全新 Windows 11 机器建议只运行一次。它基于 winget 安装以下组件并通过-Scope参数控制安装范围machine默认、需管理员权限user免提权组件winget 包 ID用途GitHub CLIGitHub.cliPublish-Release.ps1通过gh与 GitHub Releases 交互Inno Setup 6JRSoftware.InnoSetup安装包编译器ISCC.exeCertum SimplySign DesktopCertum.SmartSignSimplySignDesktop代码签名用的云证书提供商Python 3.14Python.Python.3.14运行 markdown-to-HTML 文档生成.NET SDKMicrosoft.DotNet.SDK.major编译与测试应用版本从工程自动推导其中.NET SDK的版本号并非写死而是通过Get-DotNetSdkVersion函数从 SoundSwitch/SoundSwitch.csproj 的TargetFrameworknet10.0-windows10.0.17763.0/TargetFramework正则提取主版本号当前为 10再安装对应的Microsoft.DotNet.SDK.10。这一点在 Install-BuildTools.Tests.ps1 中有专门的Get-DotNetSdkVersion测试组验证如net10.0-windows→ 10、net9.0→ 9。signtool 的四级获取策略签名工具signtool.exe的获取是脚本中最讲究的部分Install-SignTool函数依次尝试已存在于 PATH 中直接复用在C:\Program Files (x86)\Windows Kits\10\bin下递归查找x64目录中的 signtool.exe取版本号最高者Find-SignToolInWindowsKits排序逻辑见 Install-BuildTools.Tests.ps1 中返回最高版本的测试用例从 GitHub 上的 Delphier/SignTool 发布页下载独立轻量版signtool.exe解压后执行无参冒烟测试Test-SignToolWorks退出码 0 或 1 均视为可运行因为无参 signtool 会打印用法并以 1 退出确认可用缓存在%LOCALAPPDATA%\SignTool下次直接复用兜底用 winget 安装完整 Windows SDKMicrosoft.WindowsSDK.10.0.26100再回到第 2 步查找。无论哪条路径成功脚本都会把 signtool 目录同时加入当前会话 PATH与用户级 PATH[System.Environment]::SetEnvironmentVariable(Path, ..., User)保证后续Sign-Binary.ps1/Build-Installer.ps1能找到它。安装完成后脚本会提示重启终端以刷新 PATH。二、代码签名Sign-Binary.ps1 的现代签名实践Sign-Binary.ps1 是签名操作的最小封装被Build-Installer.ps1自动调用也可独立使用。其核心参数参数默认值说明-Path必填一个或多个待签名文件支持管道输入与-FullName别名-CertificateNameOpen Source Developer Antoine Aflalo证书主题名CN按名称在证书库中定位证书-TimestampUrlhttp://timestamp.digicert.comRFC 3161 时间戳服务器-MaxRetries3单文件最大签名尝试次数-RetryDelaySec5失败重试间隔秒实际签名的 signtool 命令第 119-124 行为signtool.exe sign /n $CertificateName /fd sha256 /tr $TimestampUrl /td sha512 /v $resolvedPath要点解读文件摘要用 SHA-256/fd sha256时间戳摘要用 SHA-512/td sha512完全弃用已过时的 SHA-1时间戳走 RFC 3161 协议/tr即使证书过期签名依然有效每个文件最多重试-MaxRetries次主要应对时间戳服务器临时不可用等瞬时故障见脚本第 105-133 行的重试循环定位 signtool 的方式与Install-BuildTools.ps1一致先查 PATH再回退到 Windows Kits 目录找不到则直接抛错提示先运行Install-BuildTools.ps1。独立用法示例# 签名单个可执行文件 .\tools\Sign-Binary.ps1 -Path Final\SoundSwitch.exe # 一次签名多个文件 .\tools\Sign-Binary.ps1 -Path Final\SoundSwitch.exe, Final\SoundSwitch.CLI.exe # 使用自定义证书名签名安装包 .\tools\Sign-Binary.ps1 -Path Final\Installer\SoundSwitch_Installer.exe -CertificateName My Cert三、安装包编译Build-Installer.ps1Build-Installer.ps1 职责单一仅编译并签名安装包不涉及源码构建、文档生成或 GitHub 交互这些归Publish-Release.ps1。其参数参数默认值说明-FinalDir仓库根下Final\存放二进制、文档、资源的目录必须是规范的Final\目录-SkipSigning关跳过签名即使 signtool 可用-CertificateNameOpenSource Developer, Antoine Aflalo传递给Sign-Binary.ps1-InstallerReleaseStateRelease传给 Inno Setup 的发布状态标签Release/Beta/Nightly 等-Architectureswin-x64, win-arm64逗号分隔字符串或数组均可每个架构单独跑一次 ISCC为什么-FinalDir必须是规范目录脚本第 87-94 行做了硬校验-FinalDir必须解析为仓库根下的Final\否则直接抛错。原因在于 Installer/scripts/app_defines.iss 通过硬编码相对路径..\Final\引用打包载荷ExeDir定义。若允许非规范目录ISCC 实际打包的目录会与脚本签名/清理的目录不一致——校验发生在任何破坏性操作清理、签名之前避免误清误签。工作流程校验载荷Final\必须存在且非空否则抛错提示先用Publish-Release.ps1填充签名二进制未跳过且找到 signtool 时递归查找Final\下文件名匹配*SoundSwitch*.exe/*SoundSwitch*.dll的文件排除Installer\子目录交给Sign-Binary.ps1定位 Inno Setup与 CI 工作流test-installer-build.yml逻辑一致先查注册表HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Inno Setup 6_is1与 WOW6432Node 变体再回退查 PATH逐架构编译先清理Final\下旧安装包再对每个架构映射win-x64 → x64、win-arm64 → arm64执行ISCC.exe setup.iss /DReleaseState状态 /DTargetArch架构输出从Final\移动到Final\Installer\签名安装包对Final\Installer\*Installer*.exe再次调用Sign-Binary.ps1。与 setup.iss 的联动Installer/setup.iss 顶部强制要求编译时通过/DTargetArch传入x64或arm64未定义或非法值直接#error。#if TargetArch x64分支还决定载荷目录Final\win-x64\或Final\win-arm64\app_defines.iss安装包文件名后缀x64 保留无后缀的传统名OutputBaseFilename为SoundSwitch_v版本_ReleaseState_Installer.exearm64 追加_arm64SoundSwitch_v版本_ReleaseState_Installer_arm64.exe架构约束x64 用x64compatiblearm64 用arm64ArchitecturesAllowed/ArchitecturesInstallIn64BitMode即只支持 64 位 Windowsx86 不在支持范围应用版本号MyAppVersion通过GetVersionNumbersString从所选架构载荷中的SoundSwitch.exe读取。setup.iss 还内置了多语言支持英文、德文、法文、西班牙文、意大利文、葡萄牙文、俄文、波兰文、荷兰文、简体中文、韩文语言文件见 Installer/Languages、桌面图标/加入 PATH/删除旧设置三个可选任务、卸载时移除根证书与发布者证书的certutil步骤等。注意代码签名已不在 setup.iss 中通过SignTool指令完成而是统一由Build-Installer.ps1调用Sign-Binary.ps1事后签名setup.iss 第 52-54 行有注释说明。四、完整发布编排Publish-Release.ps1Publish-Release.ps1 是发布流程的总指挥把前面各工具串成一条流水线。参数如下参数默认值说明-Channelreleaserelease找非预发布草稿或beta找预发布草稿仅下载模式使用-RepositoryBelphemur/SoundSwitchGitHub 仓库owner/repo-BuildFromSource关改为从源码构建跳过发布步骤且不要求gh-ConfigurationRelease构建配置Release/Debug/Nightly仅源码构建模式有效-SkipSigning关跳过签名-CertificateNameOpen Source Developer Antoine Aflalo传递给Build-Installer.ps1/Sign-Binary.ps1-InstallerReleaseState自动未显式指定时由-Channel推导beta →Betarelease →Release-Architectureswin-x64, win-arm64支持的架构逗号分隔或数组夜间构建只传win-x64两种入口模式默认模式下载草稿 Release要求已安装并登录 GitHub CLIgh auth login。Find-DraftRelease用gh release list --repo ... --json tagName,isDraft,isPrerelease,name --limit 30拉取最近 30 个 Release按通道筛选出最新的草稿beta 通道选isPrerelease的草稿release 通道选非预发布草稿找不到就抛错提示Has semantic-release run?——说明草稿由 CI 侧的 semantic-release 预先创建脚本消费它而非创建它。-BuildFromSource模式不依赖gh直接dotnet publish -c Configuration -r rid --self-contained true编译SoundSwitch.CLI与SoundSwitch两个项目产物归入Final\rid\同时执行第 2 步文档生成与资源打包并跳过第 4-6 步没有草稿可发布。六步流水线详解Step 1填充Final\目录。默认模式用gh release download tag --pattern SoundSwitch-v*.zip下载 CI 构建产物 zip要求恰好一个匹配文件多个会抛错解压到Final\源码构建模式则先清理bin/obj/Release/Final再做上述自包含发布。Step 2生成 HTML 文档并打包资源仅源码构建模式。调用markdown_to_html.py将以下文件转为独立 HTML源文件输出CHANGELOG.mdFinal\Changelog.htmlREADME.mdFinal\Readme.htmlTerms.mdFinal\Terms.htmlREADME.de.mdFinal\Readme.de.html同时把img\soundSwitched.png、SoundSwitch.CLI\README.md、LICENSE.txt、Terms.txt复制进Final\。文件缺失时打印跳过而不中断。下载模式中这些内容已由 CI 打进 zip因此跳过本步。Step 3委托Build-Installer.ps1透传FinalDir、InstallerReleaseState、CertificateName、Architectures和可选的SkipSigning。Step 4上传安装包到草稿 Release。对Final\Installer\*Installer*.exe逐个执行gh release upload tag file --repo repo --clobber--clobber用于覆盖同名旧资产。Step 5用 CHANGELOG 设置 Release 正文。Get-LatestChangelogEntry从 CHANGELOG.md 提取第一个## [段直到下一个## [段随后交互式询问是否在正文前追加额外说明直接回车跳过写入临时文件后gh release edit --notes-file更新。Step 6确认后发布。打印 Release 名称、Tag、通道与安装包数量等待(y/N)确认后执行gh release edit tag --draftfalse正式发布输入N则保持草稿状态并提示可稍后用同一条命令手动发布。常用命令速查# 稳定版完整发布默认走最新 release 草稿 .\tools\Publish-Release.ps1 # 发布最新 beta 草稿 .\tools\Publish-Release.ps1 -Channel beta # 仅从源码构建安装包不发布 .\tools\Publish-Release.ps1 -BuildFromSource # 完整发布但不签名 .\tools\Publish-Release.ps1 -SkipSigning # 源码构建只打 x64 安装包 .\tools\Publish-Release.ps1 -BuildFromSource -Architectures win-x64脚本质量保障tools/Install-BuildTools.Tests.ps1 中的 Pester 测试不仅覆盖Install-BuildTools.ps1的辅助函数通过解析 AST 只加载函数定义、mock 掉 winget/signtool 实现完全隔离还包含对Publish-Release.ps1/Build-Installer.ps1的语法解析校验ParseFile断言无错误、含#Requires -Version 7.0以及-InstallerReleaseState未显式指定时由-Channel推导、Build-Installer.ps1不再使用遗留的Make-Installer.bat、直接调用 ISCC.exe、通过Sign-Binary.ps1签名等行为断言——这些测试固化了工具链的契约防止回归。五、文档转换markdown_to_html.pymarkdown_to_html.py 取代了此前流水线使用的markdown-htmlnpm 包纯 Python 实现依赖 PyPI 的markdown包pip install markdown用法# 单文件转单 HTML python tools/markdown_to_html.py README.md -o Final/Readme.html # 多文件批量转到一个目录 python tools/markdown_to_html.py CHANGELOG.md Terms.md -d Final实现要点启用extra表格、围栏代码块、脚注、codehilite代码高亮无 Pygments 时优雅降级、toc[toc]占位符支持、sane_lists四个扩展输出为独立 HTML5 文档内嵌完整的 GitHub 风格 CSS_HTML_TEMPLATE不需要外部样式表即可直接浏览标题由文件名推导path.stem.replace(-, ).replace(_, ).title()-o与-d互斥argparse 互斥组-o只允许单个输入文件多文件配-o直接报错退出文件不存在或不可读时以错误信息退出输出统一打印输入 - 输出映射行。六、夜间构建分发upload_nightly_r2.pyupload_nightly_r2.py 负责把夜间构建nightly压缩包上传到Cloudflare R2S3 兼容对象存储并可选向 Discord 发送通知。夜间构建在本仓库中的定位可从 website/src/advanced/nightly.md 印证它们是未经测试、未签名的最新快照供尝鲜、翻译验证或开发者指定测试列表展示最近 5 个构建并带 SHA-512 校验和。命令行参数全部必填除标注外参数必填说明--file是要上传的构建压缩包--version是版本号--bucket是R2 bucket 名--account-id是Cloudflare 账户 ID--access-key-id/--secret-access-key是R2 API 凭据--public-base-url否公共下载 URL 前缀空则跳过 URL 生成--prefix否对象前缀默认nightly--metadata-file否版本元数据 JSON 输出路径--discord-webhook否Discord webhook URL空则跳过通知--repository否用于提交链接格式化--commit-count否通知里展示的近期提交数默认 10--commit否当前构建对应的 commit核心流程与细节客户端用 boto3 构造 S3 客户端endpoint 为https://account-id.r2.cloudflarestorage.comregion 固定auto读取既有元数据从nightly/version.json读取历史 artifact 列表兼容新旧两种元数据格式用于计算增量 changelog 与清理旧文件SHA-512 校验和分块计算1 MiB 块存入 artifact 记录供 SoundSwitch 更新器下载前校验对应 nightly 文档中updater 依据 SHA-512 校验的说明Changelog 生成用git log --no-merges --oneline取上一个 commit 到当前 commit 的提交最多 20 条按 Conventional Commits 格式正则^([\da-f]{7,})\s(\w)\((.)\)(.)$解析并渲染为带链接的列表上传与保留策略上传nightly/文件名同时只保留最近 9 个 artifact多余的从 bucket 删除retained_artifacts[:9] 计算 delete_keys随后更新nightly/version.json含latest、published、url、artifacts数组通知与 CI 输出写本地元数据文件若指定Discord webhook 发送带 embed 的消息标题New Build: version、最近 N 条提交、时间戳若环境变量GITHUB_OUTPUT存在追加version与download-url两个输出供 CI 下游步骤使用。七、工具链在发布流水线中的整体协作把上述脚本串起来SoundSwitch 的发布流程可以概括为三条路径路径 A默认草稿 Release 驱动 CI(semantic-release 创建草稿 构建产物 zip) → Publish-Release.ps1 下载 zip 到 Final\ → Build-Installer.ps1内部调用 Sign-Binary.ps1 签二进制与安装包 → gh release upload --clobber 上传安装包 → 提取 CHANGELOG 最新段落作为正文可追加用户说明 → 确认后 gh release edit --draftfalse 发布 路径 B本地从源码构建 Publish-Release.ps1 -BuildFromSource → dotnet publish 自包含发布 CLI 主程序按架构 → markdown_to_html.py 生成 Changelog/Readme/Terms 的 HTML → 复制 README/LICENSE/Terms/图片资源 → Build-Installer.ps1 编译并签名安装包 不涉及 GitHub无发布步骤 路径 C夜间构建分发 构建产物 → upload_nightly_r2.py → Cloudflare R2保留最近 9 个 version.json 元数据 SHA-512 → Discord 通知 GITHUB_OUTPUT 输出值得一提的是仓库根目录还保留了 Make.bat 与 Installer/Make-Installer.bat 作为遗留的批处理构建入口前者同样执行自包含发布与markdown-html文档生成后者按x64,arm64逐架构调用 ISCC而tools/下的 PowerShell 脚本是其现代化替代——测试用例明确断言Build-Installer.ps1does not use Make-Installer.bat (legacy)。同时注意这些脚本面向 Windows 开发机与 docs/architecture.md 描述的 .NET/WinForms 应用结构互为表里发布链路服务于主应用SoundSwitch/、CLISoundSwitch.CLI/以及多语言安装包这一整套交付物。参考文件索引工具说明总览tools/README.md环境安装tools/Install-BuildTools.ps1、测试 tools/Install-BuildTools.Tests.ps1代码签名tools/Sign-Binary.ps1安装包编译tools/Build-Installer.ps1、脚本 Installer/setup.iss、定义 Installer/scripts/app_defines.iss发布编排tools/Publish-Release.ps1文档转换tools/markdown_to_html.py夜间构建tools/upload_nightly_r2.py、说明 website/src/advanced/nightly.md遗留批处理Make.bat、Installer/Make-Installer.bat赞分享桌面应用【免费下载链接】SoundSwitchC# application to switch default playing device. Download: https://soundswitch.aaflalo.me/项目地址https://gitcode.com/gh_mirrors/so/SoundSwitch点击查看免费下载相关推荐基于 release 工具链的 AutoMQ 版本发布全流程指南从环境准备到 RC 投票基于 release 工具链的 AutoMQ 版本发布全流程指南从环境准备到 RC 投票 本指南围绕仓库 release/ 目录下的发布工具链系统讲解如何为消息队列后端云原生存储ServerBox 源码开发环境搭建与构建实战从工具链准备到发布的全流程指南ServerBox 源码开发环境搭建与构建实战从工具链准备到发布的全流程指南 ServerBox即本仓库 server_box 是一个「服务器状态与工具箱运维观测指标监控监控大盘运维3分钟打造专属桌面监控中心让闲置USB-C屏幕焕发新生3分钟打造专属桌面监控中心让闲置USB C屏幕焕发新生 你是否曾想过桌面上那个闲置的小屏幕可以变成实时监控电脑性能的智能仪表盘Turing Smart S桌面应用智能硬件上一篇【亲测免费】 React Native BLE Manager 项目常见问题解决方案下一篇CANN/asc-devkit SIMD频率统计API创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考