使用ILMerge创建已签名库时抛出异常

5

我想创建一个包含Castle.Core的FakeItEasy工具的合并版本。我了解了ILMerge,并且认为它是我所需要的解决方案。在下载和构建FakeItEasy之后,我将所需的所有文件(FakeItEasy.dll(.NET4),Castle.Core.dll(.NET4),ilmerge.exe,FakeItEasy.snk)复制到同一文件夹中。然后我运行了以下命令:

ilmerge 
    /keyfile:FakeItEasy.snk 
    /out:..\FakeItEasy.dll 
    /t:library 
    /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319 
    FakeItEasy.dll Castle.Core.dll 

并得到以下结果:
An exception occurred during merging:                                                             
An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)                                                                                                
   at System.Compiler.Writer.MscorsnStrongNameSignatureGeneration(String wszFilePath, String wszKeyContainer, Byte[] pbKeyBlob, Int32 cbKeyBlob, IntPtr ppbSignatureBlob, IntPtr pcbSignatureBlob)  
   at System.Compiler.Writer.WritePE(String location, Boolean writeDebugSymbols, Module module, Boolean delaySign, String keyFileName, String keyName)                                              
   at System.Compiler.Writer.WritePE(CompilerParameters compilerParameters, Module module)        
   at ILMerging.ILMerge.Merge()                                                                   
   at ILMerging.ILMerge.Main(String[] args) 

如果我把"/keyfile:FakeItEasy.snk"省略掉,合并后的程序集可以正常创建,但这对我没有帮助,因为我需要一个签名版本。
我还尝试指定目标平台为:
/targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319

但是结果都一样。


1
嘿,你找到答案了吗?因为我也遇到了同样的问题。 - Confused
从来没有想明白。我们最终使用通过NuGet分发的FakeItEasy版本,因此问题消失了。 - Craig W.
一个对我有效的解决方法是使用 corflags ilmerge /32bitreq+ /force,将其强制运行在32位模式下而不是64位。 - jnm2
2个回答

2

最近,当我在一个运行Windows 8 64位的新机器上设置项目时,遇到了这个问题。之前我是在Windows 7 32位虚拟机上开发,没有出现任何问题。 ILMerge命令是作为后置构建事件运行的。由于Visual Studio是一个32位进程,因此我也能够在Windows 8 64位机器上使用相同的ILMerge命令,在32位的Visual Studio命令提示符中复制这种行为。

ILMerge.exe 
   /keyfile:public.snk 
   /targetplatform:"v4,C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0" 
   /t:exe 
   /ndebug 
   /out:Result.exe Source.exe Other.dll

我在.NET应用程序和本地C++库之间进行了相当多的接口工作,因此我非常熟悉异常消息An attempt was made to load a program with an incorrect format.。这表明存在一个位数问题,例如32位进程尝试加载64位库。我认为这正是此处发生的情况。由于这是一台64位机器,我还尝试在64位Visual Studio命令提示符中使用ILMerge命令。有趣的是,但并不完全让人惊讶,与32位提示符中生成异常的相同命令在64位提示符中可以正常运行。

在开发时,我使用的是包含公钥信息的snk文件,因此我延迟签名合并的程序集。然后,我查看了ILMerge的可用命令开关,并发现了/delaysign开关。将此开关添加到ILMerge命令中可以缓解从32位进程运行ILMerge时出现的问题。

ILMerge.exe 
   /keyfile:public.snk 
   /delaysign
   /targetplatform:"v4,C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0" 
   /t:exe 
   /ndebug 
   /out:Result.exe Source.exe Other.dll

更有趣的是,当使用带有完整公钥/私钥对的snk文件时,ILMerge命令可以正常工作,无需使用/delaysign开关。因此,似乎只有在使用仅包含公钥信息的snk文件并且从32位进程启动ILMerge时才会生成异常。

有趣的是...在修复了一个损坏的Windows 10安装后,我开始在一个已经成功构建多年的项目中看到这个错误。然而,它似乎与位数无关,而与管理员权限有关。当我从提升的进程中构建时,它可以工作,否则它会失败。有什么想法吗? - Thomas Levesque

0

我在从VS 2013升级到VS 2015并尝试构建一个一直构建良好的项目时遇到了这个错误(ILMerge作为构建的一部分执行)。上面的答案提醒我私钥需要管理员访问权限。然后我想起我的新的VS 2015快捷方式没有设置为“以管理员身份运行”。一旦我以管理员身份重新启动了VS 2015,构建中的ILMerge部分就正常工作了。


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