代码之家  ›  专栏  ›  技术社区  ›  Sarah Vessels

将ilmerge与.NET 4库一起使用

  •  51
  • Sarah Vessels  · 技术社区  · 15 年前

    两个问题:

    1)基本.NET程序集未包含在ILmerged程序集中

    从.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 
    

    如果我不指定.NET 4框架目录的位置,则会从ilmerge中得到“unresolved assembly reference not allowed:system”错误。如果不指定mstest目录的位置,则会得到“Unresolved assembly reference not allowed:Microsoft.VisualStudio.QualityTools.UnitTestFramework”错误。

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

    无法解析主引用“myilmergeddll”,因为它间接依赖于.NET框架程序集“mscorlib,version=4.0,culture=neutral,publicKeyToken=b7a5c561934e089”,该程序集的版本“4.0.65535.65535”高于当前目标框架中的版本“4.0.0.0”。

    如果我然后移除 /targetplatform:v4 标记并尝试使用myilmergeddll.dll,我得到以下错误:

    类型“system.xml.serialization.ixmlserializable”是在未引用的程序集中定义的。必须添加对程序集“system.xml,version=4.0.0.0,culture=neutral,publickeytoken=b7a5c561934e089”的引用。

    看来我不该那样做。无论谁使用myilmergeddll.dll API,都不必向它引用的任何库添加引用。我怎么能避开这个?

    2)只有在使用合并的程序集时才出现类型加载异常

    编辑: 除此之外,即使我添加了对 System.Xml 在使用myilmergeddll.dll的使用者项目中,使用myilmergeddll.dll中的某些代码会出现以下异常:

    System.TypeLoadException:无法从程序集“myilMergeddll,version=1.0.1.1,culture=neutral,publicKeyToken=..”加载类型“System.Func'2”。

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

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

    特定的 Row 抛出 类型加载异常 在中的公共类中定义 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);
    }
    
    6 回复  |  直到 7 年前
        1
  •  48
  •   Hans Passant    10 年前

    有一个 very recent release 解决X64问题。如果仍有问题,请直接联系Mike Barnett(mbarnett 微软 COM)


    补遗。你的问题很严重 /lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319" 选择权。在.NET 4.5发布之后,这最近让很多程序员陷入了麻烦。那个目录是 .NET 4.0引用程序集的正确引用。它的内容将被4.5程序集覆盖,您不能再使用它以.NET 4.0安装为目标。您得到的运行时错误非常尴尬,程序无法再找到某些类型。通常轰炸[extension]属性,有时在icommand接口上。

    这些类型以及其他一些类型从一个程序集移动到另一个程序集。使用正确的参考组件是非常困难的要求。你 必须 用途:

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

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

        2
  •  21
  •   Contango    13 年前

    以下是使用.NET 4.0的Visual Studio 2010 SP1的“后期生成字符串”。我正在构建一个包含所有子.dll文件的console.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”目录:这是output.exe文件的结束位置。
    • 注意“ilmerge”目录。我将ilmerge实用程序复制到我的解决方案目录中(这样我就可以分发源代码而不必担心记录ilmerge的安装)。

    先进提示:

    如果您对它不工作有问题,请在“后期构建”命令之前添加一个“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
    

    更新

    将此添加到“后期生成”步骤中,它将所有.exe+.dll文件替换为单个组合的.exe。它还保持debugging.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
    
        3
  •  2
  •   Contango    14 年前
        4
  •  2
  •   sebagomez    13 年前

    还可以添加配置文件,其内容如下:

    <?xml version ="1.0"?>
    <configuration>
      <startup useLegacyV2RuntimeActivationPolicy="true">
        <requiredRuntime safemode="true" imageVersion="v4.0.30319" version="v4.0.30319"/>
      </startup>
    </configuration>
    

    取自 here

        5
  •  1
  •   Tony Wall    12 年前

    只需在Visual Studio属性窗口中将PresentationCore和PresentationFramework引用设置为“copy local=true”(在解决方案资源管理器中选择引用之后)。它可以在不硬编码框架路径的情况下解决问题。我喜欢这个解决方案,因为路径是不同的,这取决于开发人员/构建服务器是64位还是32位,并且随着新的.NET/VS版本的发布,不可避免地会发生变化。

        6
  •  0
  •   ursa    7 年前

    对于那些使用 ILMerge from community tasks CSPROJ:

    <ILMerge InputAssemblies="@(MergeAssemblies)"
             ...
             TargetPlatformVersion="v4"
             TargetPlatformDirectory="$(ProgramFiles)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
    />
    

    我们混合了CI构建代理,因此我们使用$(ProgramFiles)环境变量指向正确的路径(drive+x86/x64文件夹),正如建议的那样。 MSBuild Team .