ClickOnce 先决条件:错误:已发布的安装程序可能损坏。

14

我创建了一个自定义设置包,用于在客户机上安装一些字体,并将其部署到C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages\FontsInstaller的先决条件文件夹下。在 Visual Studio 2010 中引用它作为先决条件一切都很好,我能够无问题地发布应用程序。

另一方面,客户端在哈希验证期间出现错误:

正在验证文件哈希

错误:安装程序检测到文件'C:\Users\RMORAN~1\AppData\Local\Temp\VSD4684.tmp\FontsInstaller\fontsinstaller.msi'在最初发布后已更改或可能损坏。

我尝试使用 Bootstrapper Manifest Generator 包含和排除哈希值,但客户端始终得到相同的结果。由于安全原因,一旦失败哈希验证,该文件会立即被删除。

现在,我发现了一份Microsoft Connect bug报告,其中写道:

"我安装了一个自定义启动程序包,作为我的应用程序的前提条件。当我在安装了 Visual Studio 2012 的系统上构建时,安装失败,并显示以下错误:

安装程序检测到文件'...'在最初发布后已更改或可能损坏。

我是在 Visual Studio 2010 中构建的,没有对包或项目进行任何更改。没有安装Visual Studio 2012时,这个过程按预期工作。

我尝试在另一台未安装VS2012的工作站上构建此安装程序,在客户端通过了哈希验证(我遇到了签名问题,但那是另一个故事)。这真的是构建机器有VS2012的问题,而不是客户端的问题,因为在我的原始工作站上构建的软件包也在没有安装VS2012的计算机上失败。

如果还有其他人遇到了这个问题,则除了不安装VS2012之外,您是否找到了解决方法?


同样的问题!安装了vs2012之后,我的自定义启动程序包不想通过ClickOnce安装。你解决了吗? - giammin
3个回答

11
我使用了一个反射工具来查看启动程序生成的MSBuild任务(在一台安装了.NET 4.5的机器上),发现它增强了 product.xml 文件中的 <PackageFile /> 元素。具体来说,它试图从每个文件中计算公钥。如果可以找到公钥,则将其与 PublicKey 属性的值进行比较。如果值不同,则发出警告,但在两种情况下都保留刚刚计算出的值。
如果无法确定公钥,则计算文件的SHA256哈希,并使用 Hash 属性的值进行类似的比较,如果值不同,则发出警告并将 Hash 属性的值设置为计算出的值。
您可以通过提取生成的 setup.exe 中的 SETUPCFG 资源来确认这些结果;它是 product.xml 文件合并的文本版本。
总之,还记得我说过如果找不到公钥,它会计算文件的SHA256哈希吗?<PackageFiles> Element (Bootstrapper) 的文档表示,Hash 属性的值应该是一个SHA1哈希

我无法确定setup.exe使用SHA1还是SHA256来验证Hash属性的值(它是非托管代码,我找不到其符号),但请记住查看.NET 4.0版本的引导程序生成器MSBuild任务会发现它确实使用SHA1算法来计算Hash属性的值,因此我们可以通过推断说setup.bin(至少是来自Windows SDK v7.0A的版本)使用的是SHA1。 我相当确定尝试了使用来自Windows SDK v8.0A的setup.bin并得到了相同的(错误)结果。(可以通过将v8.0A SDK的setup.bin复制到仅限.NET 4.0的机器上,并查看生成的setup.exe是否可以使用基于哈希的验证安装自定义引导程序包来确认此点)

因此,如果setup引导程序中的基于哈希的验证存在问题,我们至少可以使用公钥(基于证书的)验证。好消息是,如果引导程序生成器能够从软件包文件中提取证书的公钥,则该生成器将自动开始使用此机制。坏消息是,这意味着每个软件包文件必须使用signtool.exe和有效的代码签名证书进行签名(虽然不是每个人都有一个代码签名证书,但如果您使用ClickOnce,可能会有...)。

一旦我使用有效的代码签名证书签署了我们自定义引导程序使用的软件包文件,在使用安装了.NET 4.5的机器构建项目时,运行时就不再出现安装故障,并且在使用未安装.NET 4.5的机器生成有效的引导程序仍然是可行的。

简而言之:使用代码签名证书签署软件包文件可以避免.NET 4.5中引入的缺陷。


我使用与ClickOnce应用程序相同的证书对打包文件(.msi)进行了签名。它成功地被签名了。然后为它创建了一个引导清单。但我仍然收到错误消息“文件XYZ.msi自初始发布以来已更改或可能损坏”。在日志中,我看到错误发生在“验证文件哈希”之后。在安装VS2012时安装.NET 4之前,应用程序引导程序运行得非常完美。有什么想法吗? - PUG
好的,我在我的win 7机器上安装了所有的Windows更新,并使用相同签名的包制作了清单,但错误变成了WinVerifyTrust返回-2146762487 文件不受信任 错误:安装程序检测到无法验证文件<My custom package>的发布者。这个错误只出现在没有安装我签名包的证书的机器上。但是我不能在200台机器上安装这个证书。 - PUG
是的,确认只有在我手动添加证书进入“内存管理控制台”的系统上才能工作。 - PUG
@jaminator:听起来你的证书不是受信任的代码签名证书。在你的已签名文件上:右键单击 > 属性 > 数字签名 > 详细信息 > 查看证书 > 认证路径。是否所有内容都是受信任的并来自常见的受信任根? - Olivier Dagenais
我遇到了同样的问题。它在 .Net 4.0 的机器上运行正常,但在 .NET 4.5 的机器上失败了。 - Pradeep
显示剩余2条评论

1
你需要更改GenerateBootstrapper Path,从:

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper

C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\Bootstrapper


1
你需要将GenerateBootstrapper路径从以下路径更改为:
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper 更改为
C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\Bootstrapper 并将你想要使用的msi包从以下路径复制到
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper 到
C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\Bootstrapper。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接