如何在.NET 4库中使用ILMerge?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (12)

两个问题:

1)不包含在ILMerged程序集中的基本.NET程序集

在从.NET 3.5 / Visual Studio 2008升级到.NET 4 / Visual Studio 2010后,我在构建后版本时遇到了问题。我有一个解决方案,其中有几个项目的目标框架设置为“.NET Framework 4” 。我使用下面的ILMerge命令将单个项目DLL合并到单个DLL中:

if not $(ConfigurationName) == Debug
  if exist "C:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe"
    "C:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe"
      /lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319"
      /lib:"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies"
      /keyfile:"$(SolutionDir)$(SolutionName).snk"
      /targetplatform:v4
      /out:"$(SolutionDir)bin\development\$(SolutionName).dll"
      "$(SolutionDir)Connection\$(OutDir)Connection.dll"
      ...other project DLLs...
      /xmldocs 

如果我没有指定.NET 4框架目录的位置,那么ILMerge会收到“未解析的程序集引用不允许:系统”错误。如果我不指定MSTest目录的位置,则会收到“未解析的程序集引用不允许:Microsoft.VisualStudio.QualityTools.UnitTestFramework”错误。

上面的ILMerge命令工作并生成一个DLL。但是,当我在另一个.NET 4 C#项目中引用该DLL并尝试在其中使用代码时,出现以下警告:

The primary reference "MyILMergedDLL" could not be resolved because it has an indirect dependency on the .NET Framework assembly "mscorlib, Version=4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" which has a higher version "4.0.65535.65535" than the version "4.0.0.0" in the current target framework.

如果我然后删除该/targetplatform:v4标志并尝试使用MyILMergedDLL.dll,我得到以下错误:

The type 'System.Xml.Serialization.IXmlSerializable' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

似乎我不应该那样做。无论使用我的MyILMergedDLL.dll API,都不应该添加对它引用的任何库的引用。我怎样才能解决这个问题?

2)仅当使用合并装配时,TypeLoadException

除此之外,即使我System.Xml在使用MyILMergedDLL.dll的使用者项目中添加引用,使用MyILMergedDLL.dll中的某些代码也会产生以下异常:

System.TypeLoadException: Could not load type 'System.Func`2' from assembly 'MyILMergedDLL, Version=1.0.1.1, Culture=neutral, PublicKeyToken=...'.

这是我的消费者项目中的代码; 导致这条线TypeLoadException是第二个:

var keys = new[] {"a", "b", "c"};
var row = new Row(keys);

Row抛出它的特定构造TypeLoadException函数在公共类中定义MyILMergedDLL,并且当我在引用单个项目DLL时使用此构造函数时,它工作正常。只有当我使用这个构造函数引用IL合并的DLL时,我才会得到异常。我不知道发生了什么事。

这是那个构造函数:

public Row(IEnumerable<string> keys) : base(keys) { }

base其所提到有这样的代码:

foreach (string key in keys.Where(
    key => !string.IsNullOrEmpty(key)
))
{
    _dic.Add(key, string.Empty);
}
提问于
用户回答回答于

有一个最近发布解决x64问题。如果你仍然有问题,直接与迈克·巴内特联系(Mbarnett)微软网点(COM)


增编。你的/lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319"选择。在.NET 4.5发布之后,这使许多程序员最近陷入了麻烦。那个目录是适合.NET 4.0引用程序集的。它的内容会被4.5个程序集覆盖,您不能再使用它来针对.NET 4.0安装。您得到的运行时错误非常尴尬,程序再也找不到某些类型了。通常轰炸延拓属性,有时在ICommand接口上。

这些类型和其他类型从一个程序集移动到另一个程序集。使用正确的引用程序集是一项硬要求.。你用途:

 /lib:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"

调整以匹配您的特定机器和目标框架版本。

用户回答回答于

这里是Visual Studio 2010 SP1的“Post Build String”,使用.NET 4.0。我正在构建一个包含所有子.dll文件的控制台.exe。

"$(SolutionDir)ILMerge\ILMerge.exe" /out:"$(SolutionDir)\deploy\$(TargetFileName)" "$(TargetDir)$(TargetFileName)" "$(TargetDir)*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards

基本提示:

  • 注意“\ deploy \”目录:这是输出.exe文件结束的位置。
  • 注意“ILMerge \”目录。我将ILMerge实用程序复制到我的解决方案目录中(这样我就可以分发源代码而不必担心记录ILMerge的安装问题)。

高级提示:

如果在使用中遇到问题,请在“后期制作”命令之前添加“回声”。然后,打开Visual Studio(View..Output)中的“Output”窗口,然后检查Visual Studio实际生成的确切命令。在我的具体情况中,确切的命令是:

"T:\PhiEngine\CSharp\ILMerge\ILMerge.exe" /out:"T:\PhiEngine\CSharp\Server Side\deploy\NfServiceDataHod.History.exe" "T:\PhiEngine\CSharp\Server Side\NfServiceDataHod\bin\Debug\NfServiceDataHod.History.exe" "T:\PhiEngine\CSharp\Server Side\NfServiceDataHod\bin\Debug\*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards

添加到我的“后构建”步骤,它用一个单一的组合.exe替换所有的.exe + .dll文件。它也使调试.pdb文件保持不变:

rem Create a single .exe that combines the root .exe and all subassemblies.
"$(SolutionDir)ILMerge\ILMerge.exe" /out:"$(TargetDir)$(TargetName).all.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards
rem Remove all subassemblies.
del *.dll
rem Remove all .pdb files (except the new, combined pdb we just created).
ren "$(TargetDir)$(TargetName).all.pdb" "$(TargetName).all.pdb.temp"
del *.pdb
ren "$(TargetDir)$(TargetName).all.pdb.temp" "$(TargetName).all.pdb"
rem Delete the original, non-combined .exe.
del "$(TargetDir)$(TargetName).exe"
rem Rename the combined .exe and .pdb to the original name we started with.
ren "$(TargetDir)$(TargetName).all.pdb" "$(TargetName).pdb"
ren "$(TargetDir)$(TargetName).all.exe" "$(TargetName).exe"
exit 0

扫码关注云+社区