【问题标题】:How can I force .NET to use a local copy of an assembly that's in the GAC如何强制 .NET 使用 GAC 中的程序集的本地副本
【发布时间】:2008-11-06 05:06:15
【问题描述】:

我有一个 .NET 程序集(出于我无法控制的原因)必须在 GAC 中。但是,相同的程序集被另一个程序使用,该程序具有相同程序集的旧版本的自己的副本。它必须使用自己的副本,而不是 GAC 中的任何内容。在这种情况下,正确的版本控制可能比它的价值更麻烦,原因我不会讨论。我的问题是:无论如何要告诉 .NET:只需使用此 DLL,就在此目录中 - 忽略您在 GAC 或其他任何地方找到的任何内容

【问题讨论】:

    标签: .net gac


    【解决方案1】:

    确保 GAC 程序集和本地程序集具有不同的版本号(至少,通过在 AssemblyInfo 中通配您的 AssemblyVersion 来让您的内部版本号自动递增并不是一个坏主意:[assembly: AssemblyVersion("1.0.0 .*")] )。然后,使用您应用的配置重定向您的程序集绑定:

    在您的情况下,您不需要 assemblyBinding 配置的“appliesTo”属性。你只需要这样的东西:

    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="YourAssembly" publicKeyToken="AAAAAAAAAAAA" culture="neutral"/>
                <bindingRedirect oldVersion="0.0.0.0-5.2.1.0" newVersion="5.0.8.1"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
    

    【讨论】:

    • 您能否通过重新编译应用程序以使用新版本的 dll 来避免使用此绑定重定向,或者是否总是需要更改一些配置?
    • 将版本号的修订部分设置为* 不会使其自动递增。 AssemblyVersionAttribute 上的 MSDN 文档表明它应该是随机的,但实际上 Visual Studio 使用自午夜以来的秒数除以 2。
    • 那么,您的意思是每个程序集都将在每个构建中重新版本化,即使它没有任何更改,这样我们就可以打破对 GAC 的依赖?什么是程序集绑定重定向?我唯一能想到的是它可以在产品上使用,这样如果你的项目在 GAC 中引用 5.0.8.3453 而不是 5.0.8.1 只是因为你在 dev 上重新版本化它而不进行更改,它将是重定向到 5.0.8.1。是对的吗?笨重,但我没有看到其他解决方法。
    • 我很困惑。这篇文章说它可能aip.im/2013/04/…
    【解决方案2】:

    如果它们具有相同的版本号,则答案是不能。如果您尝试加载与 GAC 程序集具有相同完整程序集名称(名称、版本、密钥)的程序集,CLR 将每次都选择 GAC 程序集。

    【讨论】:

    • 我不知道谁对此投了反对票,但我遇到了@JaredPar 所说的同样的事情,这让我发疯。它是从 GAC 加载的。我有两个全名相同的程序集,我想加载我稍微修改过的一个。皮塔饼。
    • 你试过了吗? aip.im/2013/04/…
    • 您可以使用 DNSPY 之类的方法修改 dll,使其具有不同的签名和版本。有点hackish,但它会工作。
    • @rolls 如何使用 dnspy 更改程序集版本?我试图更改版本,但编译后,它只使用初始版本。顺便说一句:我通过右键单击,属性然后详细信息选项卡来检查版本。
    • 你使用了保存模块吗?检查那里的所有选项。像我之前成功的那样做肯定是可以的。
    【解决方案3】:

    您可以设置 DEVPATH 以强制加载程序集,请参阅link text

    这并不能回答您的问题,因为它仅用于开发用途,即使如此也不真正推荐,因为它不反映生产用途。但是,我想无论如何我都会分享它,因为很高兴知道。

    【讨论】:

      【解决方案4】:

      您是否尝试过 Assembly.LoadFromFile()?这是一项手动操作,但应在需要之前将程序集加载到内存中。 .NET 然后将使用内存中的那个而不是寻找它。

      另一种方法是,如果本地程序集未签名,则可以这样区分。

      罗伯

      【讨论】:

      • 好主意,但不,它不起作用 - LoadFile() 加载正确的程序集,但是当使用引用的程序集时,它仍然从 GAC 加载。 :(
      • 没有托管方式来加载 GAC 程序集的本地副本
      • 使用 dnspy 修改 dll 的签名和版本,然后您可以强制加载您自定义的 hacked dll。
      【解决方案5】:

      我遇到了类似的问题。我通过使用ildasmilasm更改了目标dll的publicKeyToken来生成一个新的dll。然后我在项目引用中更新它以指向新的 dll。我采取的步骤是here

      这对我有用。

      【讨论】:

        【解决方案6】:

        绑定重定向不起作用的一个原因是 Oracle.ManagedDataAccess 提供程序对 dll 的搜索顺序与非托管提供程序不同。非托管提供程序从应用程序目录开始,然后查找注册表中的 dllpath,然后是 machine.config 中的 dll 路径,然后是 web.config 中的 dll 路径。根据 Oracle 文档,托管提供程序的搜索顺序如下:

        托管驱动程序将使用以下搜索顺序引用这些程序集:

        1. 全局程序集缓存
        2. Web 应用程序的 bin 目录或 Windows 应用程序的 EXE 目录
        3. x86 或 x64 子目录取决于应用程序是在 32 位还是 64 位 .NET Framework 中运行。如果应用程序是使用 AnyCPU 构建的,那么只要程序集可用,ODP.NET 就会使用正确的 DLL 位数。如果您的应用程序是 AnyCPU,Oracle 建议使用这种查找依赖程序集的方法。

        https://docs.oracle.com/en/database/oracle/oracle-database/12.2/odpnt/installODPmd.html#GUID-0E834EC7-21DF-4913-B712-2B0A07FD58FD

        因此,解决此问题的方法是取消注册 GAC 程序集,或者在您的 bin 和 web.config 中放入与 GAC 中的不同版本的 Oracle.ManagedDataAccess,如果您无法卸载它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-05-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多