---
title: 脚本、MSI 与 ClickOnce 的代码签名实践
url: https://cncertum.com/article/script-msi-clickonce-code-signing.html
date: 2026-10-22
author: SSLDUN
category: 代码签名证书
keywords: 脚本签名, MSI签名, ClickOnce签名, 代码签名, Certum, SSLDUN
license: 引用请注明来源并保留原文链接（https://cncertum.com/citation-policy.html）
---

# 脚本、MSI 与 ClickOnce 的代码签名实践

> 面向 Windows 发布场景，梳理 PowerShell 脚本、MSI 安装包与 ClickOnce 清单的签名顺序、时间戳、验签方法和常见失败原因。

代码签名不只用于 .exe。企业发布工具时，经常需要处理 PowerShell 脚本、批处理文件、MSI 安装包和 ClickOnce 应用。不同对象的签名方式、验证入口和失败表现并不一样。把签名步骤写进发布脚本，能减少“开发环境正常、用户环境被拦截”的情况。

本文讨论常见 Windows 发布对象的签名实践，不涉及绕过系统安全策略。证书类型和申请流程可参考本站代码签名证书栏目（/news/code-sign/），具体命令和平台策略以当期文档为准。

## 一、PowerShell 脚本签名

PowerShell 的执行策略会检查脚本来源。对需要分发的 .ps1 文件，可以使用代码签名证书签名，并在签名后通过 Get-AuthenticodeSignature 查看状态。执行策略不是权限边界，不能把它当成安全防护；签名的作用是让管理员确认脚本发布者，并在策略允许时正常加载。

签名前确认脚本使用 UTF-8 编码并保存为无 BOM 或符合团队规范，避免签名后因编辑器自动转换编码导致哈希变化。脚本中若包含下载、解压、注册服务等动作，应在发布说明中写清用途，减少终端安全软件的误报。

## 二、MSI 安装包签名

MSI 的签名对象是安装包文件本身。若 MSI 内嵌了 EXE、DLL 或脚本，建议先签内部文件，再签 MSI 外层。签名工具会写入 Authenticode 签名，修改 MSI 内容后签名失效。构建流程应将签名安排在打包完成后，后续步骤只做复制和校验，不再改写文件。

签名时统一添加时间戳，避免证书到期后历史安装包无法验证。发布前在干净系统执行安装、修复、升级和卸载，查看 Windows 是否显示预期发布者。若企业使用软件分发平台，确认平台是否校验签名链和时间戳。

## 三、ClickOnce 清单签名

ClickOnce 应用涉及应用清单和部署清单。签名对象不仅是可执行文件，还包括清单文件。清单中记录了文件哈希、版本和发布者信息，任何文件变更都可能导致清单与产物不匹配。建议在发布目录生成后，按“程序文件、应用清单、部署清单”的顺序处理，并在签名后执行清单校验。

ClickOnce 的更新机制会对比版本和清单。证书更换后，旧版本升级到新版本时可能出现发布者变化提示。提前规划证书续期，保持主体名称稳定，可以减少用户困惑。若必须变更主体，准备升级说明和技术支持方案。

## 四、批处理与驱动安装脚本

批处理文件本身对 Authenticode 签名的支持有限，很多场景是通过打包成 EXE、MSI 或 PowerShell 脚本后再签名。对驱动安装包，除了安装程序，还要关注 .cat 目录文件和驱动文件的签名状态。不要只签安装壳而忽略内部驱动，否则安装后仍可能加载失败。

签名后的文件应存放在只读发布目录，避免构建脚本后续写入版本资源。对外发布的压缩包应记录哈希，用户解压后可以核对文件是否与签名版本一致。

## 五、验签与故障排查

- 使用系统工具查看签名状态、签名者和时间戳，不要只看文件属性中的“数字签名”标签。
- 确认证书链完整，中间证书已正确安装或随包提供。
- 检查签名后是否还有构建步骤修改文件，尤其是版本信息和资源写入。
- 确认时间戳服务可访问，签名日志中没有超时或失败记录。
- 在无开发环境的干净虚拟机中测试，排除本机证书缓存影响。
如果验签显示“哈希不匹配”，通常说明签名后文件被改动；显示“证书链不可信”，检查根证书和中间证书；显示“无时间戳”，检查签名命令参数。不要把失败产物直接发布后再排查，用户侧的提示会放大问题。

## 六、发布流程建议

- 列出所有需要签名的对象：脚本、程序、库、安装包、清单。
- 确定签名顺序，内部文件先签，外层容器后签。
- 统一添加时间戳，保存签名日志和证书序列号。
- 签名后执行自动验签，失败即阻断发布。
- 在干净环境安装和升级，记录系统提示。
- 归档未签名产物、签名产物和哈希清单。
SSLDUN 自 2017 年起通过合同方式获得 Certum 相关产品授权，可协助企业准备代码签名证书材料并沟通审核问题。证书能否签发、签名是否被平台接受，仍取决于 CA 审核和平台规则。把发布流程做成可重复的步骤，比每次临时处理更稳妥。

## 七、CI 环境中的签名密钥管理

把签名接入持续集成后，密钥介质的管理比命令本身更重要。硬件令牌需要插在固定构建机上，构建任务只能通过受控服务调用签名接口，不能把私钥导出到普通构建节点。每个签名请求应记录发起人、版本号、产物哈希和签名时间，异常请求可以追溯。

对多产品线团队，建议按产品分配签名权限，避免一个账号可以签署所有产物。签名服务与构建日志分开保存，发布人员只能拿到签名后的只读产物。证书续期时先在测试流水线验证，再切换生产，防止新证书链或时间戳配置导致全量构建失败。

## 八、常见问题

问：脚本签名后，编辑器提示保存会怎样？
答：保存可能改变文件字节，导致签名失效。签名后的脚本应设为只读，修改后重新签名。

问：MSI 内文件未签名，只签外层可以吗？
答：外层签名有效，但内部文件解包后可能显示未知发布者。建议按发布要求分别签名。

问：ClickOnce 更换证书后能否继续升级？
答：可以升级，但用户可能看到发布者变化提示。提前测试并准备说明，避免升级中断。

---

来源：https://cncertum.com ｜ 原文：https://cncertum.com/article/script-msi-clickonce-code-signing.html
