如果仅存在 .NET 2.0 RTM,运行时如何解析对 .NET 2.0 SP1 程序集的调用
我们在安装了 .NET 2.0 SP1 的计算机上针对 .NET 2.0 构建了应用程序。该应用程序引用了 .NET SP1 中包含的一些标准 .NET 程序集(即 System.Xml.dll
)。
如果我们在装有 .net 2.0 RTM 的计算机上运行此应用程序,则该应用程序运行良好,甚至使用 System.Xml.dll 程序集。但是,当它尝试使用 2.0 RTM 中不存在但 2.0 SP1 中存在的方法时,应用程序会抛出 MethodNotFoundException。
我的问题是:运行时如何解析 System.Xml.dll?
程序集版本的修订号不同(但主要部分、次要部分和构建部分是相同的)。这意味着 2.0 RTM 和 2.0 SP1 程序集在程序集绑定过程方面有所不同。运行时应尝试查找 System.Xml.dll 2.0.50727.1378
,但它只找到 2.0.50727.42
。然后程序集绑定过程应该失败,因为 Machine.config 中不能有任何发布者策略或重定向。但绑定效果很好。怎么可能呢?
上述问题的另一个问题。
我们无法强制所有客户在其计算机上安装 .NET 2.0 SP1。如果我们从 .NET 2.0 SP1 附带 System.Xml.dll,我们如何强制我们的应用程序使用我们的应用程序附带的 System.Xml.dll?
更新1:看起来System.Xml.dll版本是2.0.0.0,而不是2.0.50727.x。这描述了运行时成功解决该问题的原因。但第二个问题仍然适用:我们可以从 SP1 中将 System.Xml.dll 与我们的应用程序一起提供并强制我们的应用程序使用它吗?
We have application built against .NET 2.0 on machine with .NET 2.0 SP1 installed. The application references some standard .NET assemblies included in .NET SP1 (i.e. System.Xml.dll
).
If we run this application on computer with .net 2.0 RTM, the application runs fine, it even uses System.Xml.dll
assembly. But when it tries to use method that doesn't exist in 2.0 RTM, but exists in 2.0 SP1 the application throws MethodNotFoundException.
My question is : How does the runtime resolve System.Xml.dll at all?
The assemblies versions differs in revision number (but the major, minor and build parts are equals). That means that 2.0 RTM and 2.0 SP1 assemblies are different in terms of assembly binding process. The runtime should try to find System.Xml.dll 2.0.50727.1378
, but it only finds 2.0.50727.42
. Then assembly binding process should fail because there can't be any Publisher policy or redirection in Machine.config. But binding works fine. How can it be?
Another one question which follows of the problem described above.
We can't force all our clients to install .NET 2.0 SP1 on their computers. If we ship System.Xml.dll from .NET 2.0 SP1, how can we force our application to use System.Xml.dll shipped with our application?
Update 1: Looks like System.Xml.dll version is 2.0.0.0, not 2.0.50727.x. That describes why the Runtime successfully resolves it. But the second question still applies: Can we ship System.Xml.dll from SP1 with our application and force our application to use it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果没有可接受的答案,我将发布我自己的答案。希望它对某人有帮助。
第一个问题是运行时如何解析服务包中的程序集。
我已经进行了更多研究并阅读了一些文章。我错误地查看了
AssemblyFileVersion
而不是AssemblyVersion
。对于.NET 2.0 SP
中的程序集,AssemblyFileVersion
为2.0.50727.1378
,对于.NET 2.0 RTM
中的程序集,它为2.0.50727.42
。是的,它们是不同的,但它是AssemblyFileVersion
,而不是AssemblyVersion
。程序集绑定过程仅使用AssemblyVersion
。但对于.NET 2.0 RTM
和.NET SPx
来说,AssemblyVersion
是2.0.0.0
。因此,RTM
和SPx
程序集在程序集绑定过程方面是相同的。我仍然感兴趣为什么 MS 没有提供带有增量
AssemblyVersion
的服务包程序集?他们可以使用相应的发布者策略来运送SP
程序集,以将程序集绑定从RTM
重定向到SP
。如果客户想要使用 RTM 版本的程序集,他们可以忽略特定程序集的发布者策略。实际上,我认为微软拒绝走这条路,因为如果客户端开始忽略某些程序集的发布者策略而不忽略其他程序集,那将是一团糟。由于BCL
程序集无法相互依赖,整个BCL
将变得不一致。第二个问题是关于是否可以将
.NET 2.0 SP1
程序集与我们的产品一起提供,并将程序集绑定从RTM
程序集重定向到SP
> 组装。简短的回答是“不,这是不可能的”。但有两种可能的解决方案,但它们都很蹩脚,只有在严格的情况下才能使用,一般来说它们根本不适用。
第一个解决方案是解除 CLR 程序集,然后使用我们的公钥再次构建它,或者我们可以完全省略强签名。现在,我们将能够引用此
RTM
程序集,而不是来自 GAC 的SP
程序集。第二种解决方案是使用
gacutil
工具将GAC中的RTM
程序集替换为SP的程序集。必须使用/f
(强制)选项。这两种解决方案都非常蹩脚。请不要使用它们。一般来说,由于程序集之间存在某些依赖性,它们无法使用。
结论
在我们的产品中,我们降级了产品,使其可以在
.NET 2.0 RTM
上运行。但我们仍然使用 .NET 3.x 中的一些功能(linq-to-objects
、Action
、Func
>)。我们只是随产品一起提供一些 3.x 程序集,例如System.Core.dll
。大多数情况下,我们对这种方法没有任何问题。但由于一些无法解决的问题,我们也不得不拒绝使用Linq-to-Xml
。If there is no acceptable answers I'll post my own. Hope it helps somebody.
The first question was how does runtime resolves assemblies from service pack.
I've investigated a little more and have read some articles. I mistakenly have taken a look at
AssemblyFileVersion
instead ofAssemblyVersion
. For assemblies in.NET 2.0 SP
AssemblyFileVersion
is2.0.50727.1378
, and for assemblies from.NET 2.0 RTM
it's2.0.50727.42
. Yes, they are different, but it isAssemblyFileVersion
, notAssemblyVersion
. And assembly binding process usesAssemblyVersion
only. ButAssemblyVersion
is2.0.0.0
for.NET 2.0 RTM
and.NET SPx
either. SoRTM
andSPx
assemblies are identical in terms of assembly binding process.I'm still interested why MS hadn't shipped service pack's assemblies with incremented
AssemblyVersion
? They could shipSP's
assemblies with corresponding Publisher policies to redirect assembly binding fromRTM
toSP
. And if clients would like to useRTM
versions of assemblies, they can ignore publisher policy for particular assemblies. Actually, I think that MS refused to go that way because it would be a total mess if client start to ignore publisher policies on some assemblies and don't ignore on others. ThanBCL's
assemblies couldn't rely on each other, the wholeBCL
would become inconsistent.The second question was about the possibility to ship
.NET 2.0 SP1
assemblies with our product and to redirect assembly binding fromRTM
assembly toSP's
assembly.The short answer is "no, it is not possible". But there are 2 possible solutions, but they are quite lame and can be of use only under strict circumstances and in general they are not applicable at all.
The first solution is to disasm CLR assembly and then build it again but with our public key, or we can omit strong-signing at all. Now we will be able to reference this
RTM
assembly rather thanSP's
assembly from GAC.The second solution is to replace
RTM's
assembly in GAC with SP's assembly using thegacutil
tool. The/f
(force) option must be used.Both of these two solutions are very lame. Please, don't use them. In general they can't be used due to some dependencies between assemblies.
Conclusion
In our product we downgraded our product so it could work on
.NET 2.0 RTM
. But we still use some functionality even from.NET 3.x
(linq-to-objects
,Action
,Func
). We just ship some of the 3.x assemblies with our product, e.g.System.Core.dll
. Mostly we have no problems with this approach. But we also had to decline usingLinq-to-Xml
because of some unsolvable problems..NET 版本控制仅针对强名称程序集强制执行。
您不能(也不应该)期望使用 SP1 编译的程序能够在 RTM 版本上正确运行。它可能会正确运行,但也可能会以神秘的方式失败。
.NET versionings are only enforced for strong-named assemblies.
You cannot (and should not) expect a program to run correctly on RTM version when it is compiled using SP1. It may run correctly, but it may also fail in mysterious ways.