签名EXE时出现“文件的计算哈希与清单中指定的不同”错误

6

我的ClickOnce安装失败了,并出现以下错误:

文件WindowsFormsProject.exe在清单中指定的哈希值与计算哈希值不同。

我使用MSBuild生成ClickOnce部署包。下面是构建脚本中相关的行:

<MSBuild Targets="Publish"
         Projects="WindowsFormsProject.csproj"
         ContinueOnError="false" />

WindowsFormsProject.csproj有一个后期构建步骤,用于签署可执行文件,如下所示:

signtool sign /a $(ProjectDir)\obj\$(PlatformName)\$(ConfigurationName)\$(TargetFileName)

问题在于,当我查看构建日志时,我发现清单是在Post-Build事件执行之前生成的。因此,哈希码不匹配并不奇怪。以下是构建日志中相关的行:
_CopyManifestFiles: WindowsFormsProject -> ...\WindowsFormsProject.application ... PostBuildEvent: 成功签名:...\WindowsFormsProject.exe 因此,问题是:
1. 有没有办法在 <MSBuild> 任务期间生成清单之前签署程序集? 2. 是否有办法在构建完成后重新生成清单(仅限清单),以使哈希码再次匹配?
如果你有其他解决方案,请告诉我。
3个回答

7

如果您正在使用MSBuild 4,您可以使用 AfterTargets 属性在程序集创建后立即签名,而不是执行任何进一步的步骤。删除您的后构建步骤,并将此块添加到您的项目中:

<Target Name="SignOutput" AfterTargets ="CoreCompile">
  <PropertyGroup>
    <TimestampServerUrl>http://timestamp.verisign.com/scripts/timstamp.dll</TimestampServerUrl>
  <ApplicationDescription>Foo bar</ApplicationDescription>
  <SigningCertificateCriteria>/sha1 578a9486f10ed1118f2b5f428afb842e3f374793</SigningCertificateCriteria>
  </PropertyGroup>
  <ItemGroup>
    <SignableFiles Include="$(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)\$(TargetName)$(TargetExt)" />
  </ItemGroup>
  <GetFrameworkSdkPath>
          <Output
              TaskParameter="Path"
              PropertyName="SdkPath" />
  </GetFrameworkSdkPath>
    <Exec Command="&quot;$(SdkPath)bin\signtool&quot; sign $(SigningCertificateCriteria) /d &quot;$(ApplicationDescription)&quot; /t &quot;$(TimestampServerUrl)&quot; &quot;%(SignableFiles.Identity)&quot;" />
</Target>

如果有人犯了和我一样的错误... 我曾经将答案中的 Postbuild 解释为 Target,这是不正确的。'Target' 应该在项目级别上。 - Al Lelopath

3
荣誉归于Dmitriy的答案。但我必须对Dmitry的答案进行轻微更改才能使其对我起作用。具体来说:
  • 我为“目标”添加了一个结束标记
  • 我使用的是Windows 8.1,并且必须更改signtool.exe路径
  • 我正在使用PFX文件并且必须指定密码
  • 我不需要添加他提供的所有信息

请修改“my_signing_file.pfx”,“mypassword”,“myexe.exe”的值,以使其适用于您:

<Target Name="SignOutput" AfterTargets="CoreCompile">
<Exec Command="&quot;C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe&quot; sign /f &quot;$(ProjectDir)my_signing_file.pfx&quot; /p mypassword &quot;$(ProjectDir)obj\$(ConfigurationName)\myexe.exe&quot;" />
</Target>

这个应该放在哪个文件里? - Al Lelopath
1
项目文件 (*.csproj) - BlueSky

1
您可以从Visual Studio中配置程序集和ClickOnce清单的签名过程:
  1. 右键单击项目>属性>签名。
  2. 勾选“签署ClickOnce清单”并选择要使用的证书。
  3. 勾选“签署程序集”并选择要使用的证书。
  4. 保存所有更改并重新发布。

所有这些设置将在使用MsBuild构建时生效。

注意:如果需要,您可以从该屏幕生成自签名证书。

注意2:请记住,您有两个清单,“应用程序清单”和“部署清单”,两者都必须使用相同的证书进行签名。

如果需要在构建后任何时间重新签署清单,则可以使用Mage.exe


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