将 ILMerge 与 .NET 4 库一起使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2961357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
using ILMerge with .NET 4 libraries
提问by Sarah Vessels
Two problems:
两个问题:
1) Basic .NET Assembly Not Included in ILMerged Assembly
1) ILMerged 程序集中不包含基本 .NET 程序集
I'm having trouble using ILMerge in my post-build after upgrading from .NET 3.5/Visual Studio 2008 to .NET 4/Visual Studio 2010. I have a Solution with several projects whose target framework is set to ".NET Framework 4". I use the following ILMerge command to merge the individual project DLLs into a single DLL:
从 .NET 3.5/Visual Studio 2008 升级到 .NET 4/Visual Studio 2010 后,我在后期构建中使用 ILMerge 时遇到问题。我有一个解决方案,其中包含多个目标框架设置为“.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
If I leave off specifying the location of the .NET 4 framework directory, I get an "Unresolved assembly reference not allowed: System" error from ILMerge. If I leave off specifying the location of the MSTest directory, I get an "Unresolved assembly reference not allowed: Microsoft.VisualStudio.QualityTools.UnitTestFramework" error.
如果我不指定 .NET 4 框架目录的位置,我会从 ILMerge 收到“不允许未解析的程序集引用:系统”错误。如果我不指定 MSTest 目录的位置,则会收到“不允许未解析的程序集引用:Microsoft.VisualStudio.QualityTools.UnitTestFramework”错误。
The ILMerge command above works and produces a DLL. When I reference that DLL in another .NET 4 C# project, however, and try to use code within it, I get the following warning:
上面的 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.
无法解析主要引用“MyILMergedDLL”,因为它间接依赖于 .NET Framework 程序集“mscorlib, Version=4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”,该程序集的版本高于版本“4.0.65535.65535”当前目标框架中的“4.0.0.0”。
If I then remove the /targetplatform:v4flag and try to use MyILMergedDLL.dll, I get the following error:
如果我随后删除该/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'.
类型“System.Xml.Serialization.IXmlSerializable”是在未引用的程序集中定义的。您必须添加对程序集“System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”的引用。
It doesn't seem like I should have to do that. Whoever uses my MyILMergedDLL.dll API should not have to add references to whatever libraries it references. How can I get around this?
看来我不应该这样做。使用我的 MyILMergedDLL.dll API 的人不应该添加对它引用的任何库的引用。我怎样才能解决这个问题?
2) TypeLoadException Only When Using Merged Assembly
2) TypeLoadException 仅在使用合并程序集时
Edit:beyond this, even if I do add a reference to System.Xmlin the consumer project that uses MyILMergedDLL.dll, making use of some code in MyILMergedDLL.dll gives this exception:
编辑:除此之外,即使我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=...'.
System.TypeLoadException: 无法从程序集“MyILMergedDLL, Version=1.0.1.1, Culture=neutral, PublicKeyToken=...”加载类型“System.Func`2”。
This is the code in my consumer project; the line that caused the TypeLoadExceptionis the second one:
这是我的消费者项目中的代码;导致的行TypeLoadException是第二个:
var keys = new[] {"a", "b", "c"};
var row = new Row(keys);
The particular Rowconstructor that throws the TypeLoadExceptionis defined in a public class in MyILMergedDLL, and when I use this constructor when referencing the individual project DLLs, it works fine. It is only when I use this constructor when referencing the IL-merged DLL that I get the exception. I don't know what's going on.
Row抛出 的特定构造TypeLoadException函数在 中的公共类中定义MyILMergedDLL,当我在引用单个项目 DLL 时使用此构造函数时,它工作正常。只有当我在引用 IL 合并的 DLL 时使用此构造函数时,才会出现异常。我不知道发生了什么。
Here's that constructor:
这是构造函数:
public Row(IEnumerable<string> keys) : base(keys) { }
And the baseto which it is referring has this code:
而base其所提到有这样的代码:
foreach (string key in keys.Where(
key => !string.IsNullOrEmpty(key)
))
{
_dic.Add(key, string.Empty);
}
采纳答案by Hans Passant
There was a very recent releaseto solve x64 problems. Get in touch with Mike Barnett directly if you still have problems (mbarnett atmicrosoft dotcom)
有一个非常最近发布解决问题的x64。如果您仍有问题,请直接与 Mike Barnett 联系(mbarnett atmicrosoft dotcom)
Addendum. There's something very, very wrong about your /lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319"option. This has been getting lots of programmers in trouble lately, after .NET 4.5 was released. That directory is notthe proper one for .NET 4.0 reference assemblies. Its content gets overwritten with the 4.5 assemblies, you can no longer use it to target a .NET 4.0 install. The runtime error you get is very awkward, the program cannot find certain types anymore. Usually bombing on the [Extension] attribute, sometimes on the ICommand interface.
附录。你的/lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319"选择有一些非常非常错误的地方。在 .NET 4.5 发布后,这最近让很多程序员陷入困境。该目录不适用于 .NET 4.0 参考程序集。它的内容被 4.5 程序集覆盖,您不能再使用它来定位 .NET 4.0 安装。你得到的运行时错误很尴尬,程序再也找不到某些类型了。通常轰炸[Extension]属性,有时轰炸ICommand界面。
These types, and some others, were moved from one assembly to another. Using the correct reference assemblies is a rock-hard requirement. You mustuse:
这些类型以及其他一些类型从一个程序集移动到另一个程序集。使用正确的参考组件是一项坚如磐石的要求。您必须使用:
/lib:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
Adjust to match your particular machine and target framework version.
调整以匹配您的特定机器和目标框架版本。
回答by Contango
Here is the "Post Build String" for Visual Studio 2010 SP1, using .NET 4.0. I am building a console .exe with all of the sub-.dll files included in it.
这是使用 .NET 4.0 的 Visual Studio 2010 SP1 的“生成后字符串”。我正在构建一个包含所有子 .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
Basic hints:
基本提示:
- Notice the "\deploy\" directory: this is where the output .exe file ends up.
- Notice the "ILMerge\" directory. I copied the ILMerge utility into my solution directory (so I could distribute the source without having to worry about documenting the install of ILMerge).
- 注意“\deploy\”目录:这是输出 .exe 文件结束的地方。
- 注意“ILMerge\”目录。我将 ILMerge 实用程序复制到我的解决方案目录中(这样我就可以分发源代码而不必担心记录 ILMerge 的安装)。
Advanced hints:
进阶提示:
If you have problems with it not working, add an "echo" before the "Post Build" command. Then, open the "Output" window in Visual Studio (View..Output), and check the exact command that Visual Studio actually generated. In my particular case, the exact command was:
如果您遇到无法正常工作的问题,请在“Post Build”命令之前添加“echo”。然后,在 Visual Studio 中打开“输出”窗口(View..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
Update
更新
Added this to my "Post Build" step, it replaces all .exe + .dll files with a single combined .exe. It also keeps the debugging .pdb file intact:
将此添加到我的“构建后”步骤中,它将所有 .exe + .dll 文件替换为单个组合的 .exe。它还保持调试 .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
回答by Contango
Other alternatives:
其他选择:
- Combining multiple assemblies into a single EXE for a WPF application.
- .Net Reactor.
- SmartAssembly(a quite pricey commercial alternative).
- 将多个程序集合并到一个 WPF 应用程序的单个 EXE 中。
- .Net 反应器。
- SmartAssembly(一种相当昂贵的商业替代品)。
回答by sebagomez
回答by Tony Wall
Just set PresentationCore and PresentationFramework references to have "Copy Local = True" in the Visual Studio properties window (after selecting the references in the Solution Explorer). It will solve the problem without hard-coding the framework path. I prefer this solution because the path is different depending on whether the developer/build server is 64bit or 32bit and inevitably will change as new .NET/VS versions are released.
只需在 Visual Studio 属性窗口中将 PresentationCore 和 PresentationFramework 引用设置为“Copy Local = True”(在解决方案资源管理器中选择引用后)。它将在不硬编码框架路径的情况下解决问题。我更喜欢这个解决方案,因为路径是不同的,具体取决于开发人员/构建服务器是 64 位还是 32 位,并且不可避免地会随着新的 .NET/VS 版本的发布而改变。
回答by ursa
For those, who use ILMerge from community tasksin .csproj:
对于那些从.csproj 中的社区任务使用ILMerge 的人:
<ILMerge InputAssemblies="@(MergeAssemblies)"
...
TargetPlatformVersion="v4"
TargetPlatformDirectory="$(ProgramFiles)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
/>
We have mixed park of CI build agents, so we use $(ProgramFiles) environment variable to point correct path (drive + x86/x64 folder), as it was recommended by MSBuild Team.
我们有多个 CI 构建代理,因此我们使用 $(ProgramFiles) 环境变量来指向正确的路径(驱动器 + x86/x64 文件夹),这是MSBuild Team推荐的。

