【发布时间】:2010-11-02 17:46:42
【问题描述】:
有什么办法可以强制我的 asp.net 应用程序从本地 bin 目录加载程序集,因为 gac 中有另一个同名的旧版本的程序集?
我无法删除 gac 版本,因为其他应用程序正在使用它,并且在将新版本添加到 gac 时遇到了一些困难。
【问题讨论】:
-
您是否将“特定版本”设置为 true?当然,在这种情况下,它不应该使用 GAC 的旧版本。
有什么办法可以强制我的 asp.net 应用程序从本地 bin 目录加载程序集,因为 gac 中有另一个同名的旧版本的程序集?
我无法删除 gac 版本,因为其他应用程序正在使用它,并且在将新版本添加到 gac 时遇到了一些困难。
【问题讨论】:
找到了
要强制您的应用程序从本地 bin 目录读取,您必须从程序集中删除签名,然后应用程序将从 bin 加载程序集。
感谢 Wyatt Barnett 和 murad。
【讨论】:
DEVOVERRIDE 环境变量设置为您的程序集的路径,该路径将在 GAC 之前进行探测。
更改版本号,强命名程序集并引用您使用解决方案部署的强命名的更高版本。
【讨论】:
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" />
就是这样。
【讨论】:
作为建议的解决方案的替代方案,在开发过程中,您可以通过设置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"
【讨论】:
DEVPATH 上的操作方法,我认为它与我上面的信息相匹配,只是它说(逻辑上)你必须确保DEVPATH 可访问以获取读/写权限。它还表明developerInstallation="true" 可以在应用程序级别使用,这是个好消息(我还没有测试过)。
基于此答案中关于程序集加载顺序的摘录说明: How to prevent a .NET application from loading/referencing an assembly from the GAC?
我猜想在要求库作为程序集加载之前调用本地 DLL 文件的 LoadLibrary,可能将它按搜索顺序向上移动。
遗憾的是,我不确定如何在框架开始加载引用的程序集之前让您的 LoadLibrary 调用运行。
所以这只是一个想法,而不是完整的答案。
【讨论】:
要将一个版本重定向到另一个版本,请使用
s
【讨论】:
您可以指定 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 中,然后在 GAC 中引用它?
【讨论】: