【问题标题】:Forcing the ASP.NET Application to load the assembly from bin not from GAC强制 ASP.NET 应用程序从 bin 而不是 GAC 加载程序集
【发布时间】:2010-11-02 17:46:42
【问题描述】:

有什么办法可以强制我的 asp.net 应用程序从本地 bin 目录加载程序集,因为 gac 中有另一个同名的旧版本的程序集?

我无法删除 gac 版本,因为其他应用程序正在使用它,并且在将新版本添加到 gac 时遇到了一些困难。

【问题讨论】:

  • 您是否将“特定版本”设置为 true?当然,在这种情况下,它不应该使用 GAC 的旧版本。

标签: asp.net binary gac


【解决方案1】:

找到了

要强制您的应用程序从本地 bin 目录读取,您必须从程序集中删除签名,然后应用程序将从 bin 加载程序集。

感谢 Wyatt Barnett 和 murad。

【讨论】:

  • 如果我无法从程序集中删除强名称怎么办?
  • 您能提供从程序集中删除签名的过程吗?
  • 只删除强名称文件
  • @Amitabh,您无法从没有源代码的程序集中删除签名。作为一个技巧,您可以将DEVOVERRIDE 环境变量设置为您的程序集的路径,该路径将在 GAC 之前进行探测。
  • @Abel 你有这个 DEVOVERRIDE 解决方案的链接吗?
【解决方案2】:

更改版本号,强命名程序集并引用您使用解决方案部署的强命名的更高版本。

【讨论】:

  • 我试了一下,但它也从 gac 加载程序集
  • 忘记添加“更改版本号”步骤。那你应该是金色的。
【解决方案3】:

Muse VSExtensions 建议的 oldVersion 配置有效!您可以为本地程序集使用强名称: 请看这个页面: http://msdn.microsoft.com/en-us/library/7wd6ex19.aspx

基本上在 web.config 中添加如下内容:

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="DllName"
          publicKeyToken="0123456789abc"
          culture="neutral" />        
        <!-- Assembly versions can be redirected in app, 
          publisher policy, or machine configuration files. -->
        <bindingRedirect oldVersion="2.0.0.0-2.5.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>      
    </assemblyBinding>  
  </runtime>

这样,如果我在 gac 中有一个可以从版本 2.0.0.0 到版本 2.5.0.0 的程序集,所有调用都将被重定向到 newVersion (3.0.0.0)

在程序集部分我添加了程序集:

<add assembly="DllName, Version=3.0.0.0, Culture=neutral, PublicKeyToken=0123456789abc" />

就是这样。

【讨论】:

    【解决方案4】:

    作为建议的解决方案的替代方案,在开发过程中,您可以通过设置DEVPATH environment variable 并在machine.config 中启用Development Mode 来绑定到您想要完全覆盖GAC 的任何程序集。我认为这是迄今为止实现您想要的最简单的方法,但不应该在生产中使用。

    这解决了你的程序集版本和GAC中的版本相同的问题,如果版本不同,你应该使用几个用户在这里提到的bindingRedirect方法。

    首先,将以下内容添加到machine.config

    <configuration>
      <runtime>
        <developmentMode developerInstallation="true"/>
      </runtime>
    </configuration>
    

    然后,将DEVPATH 环境变量设置为未签名程序集的位置。这将强制 Fusion 的 DEVOVERRIDE 模式启动并在探测 GAC 之前搜索 DEVPATH(及其子目录)。

    An FAQ of DEVPATH and DEVOVERRIDE on MSDN 将回答有关使用此效果的大多数问题。

    Fusion(.NET 的程序集加载器)将仅按名称和版本进行搜索,它会将强命名程序集视为等同于其他程序集,在搜索 DEVPATH 之前不会搜索 GAC,并仅返回找到的第一个匹配项。您应该使用Fusion Log Viewer (fuslogvw) 来查看您是否正确启用了它,as explained in this blog post on DEVPATH

    刚开始使用 FusLogVw? Scott Hanselman wrote an excellent intro。 Viewer 的界面相当陈旧,需要一点时间来适应。

    请注意,Fusion Log Viewer(或Assembly Binding Log Viewer,名称中的含义)会混淆地指出您使用了DEVOVERRIDE 环境变量。它应该看起来像这样:

    LOG: Found assembly in DEVOVERRIDE path D:\testassemblies\Test.DLL
    

    注意:如果您希望 Visual Studio 从 DEVPATH 位置加载程序集,您需要 should set a registry key to this location,即设置(检查 .NET 版本密钥以匹配您的 .NET 版本):

    [HKEY_CURRENT_USER\
        SOFTWARE\
        Microsoft\
        .NETFramework\
        v2.0.50727\AssemblyFoldersEx\
        DEVPATH]@="C:\SharedAssemblies"
    

    【讨论】:

    • 在我的机器上,它仍然最终从 GAC 加载。它识别 DEVPATH 并将其记录在 Fusion 日志中,但仍然不会从那里加载程序集。任何想法? DEVPATH 和 GAC 的程序集都经过签名并具有相同的身份。
    • @Turbo:我找到了this post on PDB's,它还扩展到DEVPATH 上的操作方法,我认为它与我上面的信息相匹配,只是它说(逻辑上)你必须确保DEVPATH 可访问以获取读/写权限。它还表明developerInstallation="true" 可以在应用程序级别使用,这是个好消息(我还没有测试过)。
    • @Turbo,还有一件事,也许你的意思是 VS 不识别 DEVPATH?考虑到这一点,我更新了答案,您还需要为 VS 设置注册表值才能找到该路径。
    • 感谢链接。我正在使用 vstest.console.exe 运行单元测试,我希望它从构建文件夹而不是 GAC 加载程序集。正如 pdb 帖子中所建议的,我为所有用户和应用程序包提供了读/写权限。我将 DEVPATH 设置为系统范围的环境变量。并在 machine.config 和 vstest.console.exe.config 中设置 developerInstallation="true"。和以前一样,融合日志提到了 DEVPATH 值“LOG: DEVPATH = C:\MyPath”,但它看起来并不存在(融合说它在 GAC 中找到了程序集,而在 DEVPATH 中没有任何探测)。
    • 当 DEVPATH 未定义且 developerInstallation 为 true 时,我还看到一个异常,这意味着 fusion 知道,但它没有使用它。
    【解决方案5】:

    基于此答案中关于程序集加载顺序的摘录说明: How to prevent a .NET application from loading/referencing an assembly from the GAC?

    我猜想在要求库作为程序集加载之前调用本地 DLL 文件的 LoadLibrary,可能将它按搜索顺序向上移动。

    遗憾的是,我不确定如何在框架开始加载引用的程序集之前让您的 LoadLibrary 调用运行。

    所以这只是一个想法,而不是完整的答案。

    【讨论】:

      【解决方案6】:

      要将一个版本重定向到另一个版本,请使用 元素。 oldVersion 属性可以指定单个版本或一系列版本。例如,指定运行时应使用 2.0.0.0 版本,而不是 1.1.0.0 和 1.2.0.0 之间的程序集版本。

      s

      【讨论】:

      • 在哪里可以找到这个 oldVersion 属性?
      【解决方案7】:

      您可以指定 codebase 路径,而不是使用 bindingRedirect。我有一个 MySQL.Data.dll 的工作示例。

      <dependentAssembly>
          <assemblyIdentity name="MySql.Data" publicKeyToken="c5687fc88969c44d" culture="neutral" />
          <codebase version="5.2.5.0" href="/bin/MySQL.Data.dll" />        
        </dependentAssembly>
      

      这可以在 Web 应用程序的 Web.config 中完成。

      【讨论】:

      • 在 GAC 中查找后查看 CodeBase 中的路径。因此,如果程序集在 GAC 中(如问题中所述),那么这将不起作用。
      【解决方案8】:

      为什么不将您喜欢的版本安装到 GAC 中,然后在 GAC 中引用它?

      【讨论】:

      • 遗憾的是,旧版本拒绝从 GAC_32 卸载,因为它仍在被某些未知应用程序使用。双重遗憾的是,新版本的版本号与旧版本完全相同。在 GAC_MSIL 中安装新版本不会阻止系统选择使用 GAC_32 旧版本。
      猜你喜欢
      • 2018-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-09
      相关资源
      最近更新 更多