如果 Visual Studio 中的 ClickOnce 代码签名功能不起作用,如何签名 ClickOnce 部署
如何正确签名 ClickOnce 部署,使其真正有效
引言
最近,我开发了一个 WPF 桌面应用程序。这个应用程序将从网站上下载,所以我们需要一个安装程序来在客户的计算机上安装这个应用程序。应用程序和安装程序都必须进行代码签名,以避免被 SmartScreen 和防病毒程序阻止。
我决定使用 ClickOnce 技术,因为它似乎是生成安装程序的最简单方法,并且它提供自动更新。不幸的是,很快发现对 ClickOnce 部署进行代码签名是一项相当困难的任务。互联网上有一些关于如何对 ClickOnce 部署进行签名的提示,但它们没有涵盖整个主题,所以我决定写下我如何自己解决这个问题。
背景
ClickOnce 部署由四个部分组成
- 应用程序文件
- 应用程序清单
- 部署清单
- 引导程序文件 (setup.exe)
重要的是,这四个元素必须单独签名。许多开发人员只对应用程序文件或仅对清单进行签名。这可能导致部署错误,并且 SmartScreen 过滤器仍然会阻止未正确签名的应用程序。
在 Visual Studio 中对 ClickOnce 部署进行签名
首先,不要使用这个
这些选项理论上应该会自动对您的 ClickOnce 清单进行签名,但它们不允许您为 signtool 指定命令行参数,因此它们无法与某些电子签名一起使用。您必须做的是手动编辑您的项目文件并添加一些部署目标。
1. 对应用程序文件进行签名
右键单击您的项目并选择“卸载项目”。然后右键单击卸载的项目并选择“编辑 <项目名称>.csproj”。代码编辑器出现。
滚动到底部,并在最后一个结束的 </Project>
标签之前添加一个新目标
<Target Name="AfterCompile" Condition="
'$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Exec Command=""C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe"
sign /n "InsertNameHere" /t http://yourtimestampuri /fd sha1
/v "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)"" />
</Target>
当然,您必须用操作系统中正确的 signtool 路径替换“C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe”,并为 signtool 提供有效的命令行参数。通常,电子签名经销商会提供关于如何正确使用 signtool 的教程。
上面的代码片段对应用程序文件进行签名。现在您必须对两个清单和引导程序文件进行签名。
2. 对应用程序清单进行签名
<Target Name="SignManifest" AfterTargets="_DeploymentSignClickOnceDeployment"
Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
</Target>
现在我们将向此目标标签添加四个命令。首先,我们必须对应用程序清单进行签名
<Exec Command=""C:\Program Files
(x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools\mage.exe"
-Sign "$(_DeploymentApplicationDir)$(_DeploymentTargetApplicationManifestFileName)"
-CertHash INSERTVALIDHASHHERE -TimeStampUri http://yourtimestampuri" />
Mage.exe 是一个用于编辑和签名 ClickOnce 清单的工具。您将必须在您的系统中找到它并提供该文件的有效路径。
3. 更新部署清单以引用已签名的应用程序清单版本
上面的命令对应用程序清单进行签名。您现在有一个已签名的应用程序清单和未签名的部署清单。现在对部署清单进行签名没有用,因为它仍然引用应用程序清单的未签名版本。您必须更新生成的部署清单以引用已签名的应用程序清单版本
<Exec Command=""C:\Program Files
(x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools\mage.exe"
-Update "$(PublishDir)$(TargetDeployManifestFileName)"
-AppManifest "$(_DeploymentApplicationDir)$(_DeploymentTargetApplicationManifestFileName)"" />
4. 对部署清单进行签名
部署清单现在引用了正确的应用程序清单,因此我们现在可以对其进行签名
<Exec Command=""C:\Program Files
(x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools\mage.exe"
-Sign "$(PublishDir)$(TargetDeployManifestFileName)"
-CertHash INSERTVALIDHASHHERE -TimeStampUri http://yourtimestampuri" />
5. 对引导程序文件进行签名
我们已经对两个清单进行了签名。现在我们只需要对 setup.exe 文件进行签名
<Exec Command=""C:\Program Files
(x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe"
sign /n "CertificateName" /t http://yourtimestampuri /fd sha1
/v "$(PublishDir)\setup.exe"" />
就这样。ClickOnce 部署的所有四个元素现在都已正确签名。
摘要
这是您必须插入到 .csproj 文件中的完整代码
<Target Name="AfterCompile" Condition="
'$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Exec Command=""C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe"
sign /n "InsertNameHere" /t http://yourtimestampuri /fd sha1
/v "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)"" />
</Target>
<Target Name="SignManifest" AfterTargets="_DeploymentSignClickOnceDeployment"
Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Exec Command=""C:\Program Files
(x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools\mage.exe"
-Sign "$(_DeploymentApplicationDir)$(_DeploymentTargetApplicationManifestFileName)"
-CertHash INSERTVALIDHASHHERE -TimeStampUri http://yourtimestampuri" />
<Exec Command=""C:\Program Files
(x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools\mage.exe"
-Update "$(PublishDir)$(TargetDeployManifestFileName)"
-AppManifest "$(_DeploymentApplicationDir)$
(_DeploymentTargetApplicationManifestFileName)"" />
<Exec Command=""C:\Program Files
(x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools\mage.exe"
-Sign "$(PublishDir)$(TargetDeployManifestFileName)"
-CertHash INSERTVALIDHASHHERE -TimeStampUri http://yourtimestampuri" />
<Exec Command=""C:\Program Files
(x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe"
sign /n "CertificateName" /t http://yourtimestampuri /fd sha1
/v "$(PublishDir)\setup.exe"" />
</Target>
关注点
电子签名经销商为您提供两种类型的代码签名证书:标准代码签名和扩展验证代码签名。第二种类型会立即删除 SmartScreen 警告,当客户尝试安装您的应用程序时。第一种类型的证书会在您的应用程序收集到声誉点后一段时间内删除 SmartScreen 警告。在我看来,扩展验证证书不值得购买。我们使用标准证书,并且在产品发布后大约两周,SmartScreen 过滤器消息就消失了。从那时起,我们再也没有看到 SmartScreen 消息。