装配加载版本不匹配:为什么加载? [英] Assembly Loading Version Mismatch: Why is it loading?

查看:261
本文介绍了装配加载版本不匹配:为什么加载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个程序集:HelloWorld.exe和Hello.dll。我们编译了HelloWorld.exe(1.0.0)和Hello.dll(1.0。),这个主程序集是主程序集,而dll被主程序所使用。



< 0)。我将程序集放在不同的文件夹上。



然后,我将Hello.dll的版本更改为2.0.0,并继续覆盖Hello.dll 1.0.0 2.0.0版本。我然后启动HelloWorld.exe,它工作正常。



我预计它会立即崩溃并刻录,因为在编译EXE时引用的Hello.dll是1.0.0。现在,1.0.0的DLL已被2.0.0所替代,但仍然有效!



根据 MSDN



默认情况下,程序集只会使用完全相同的程序集(名称和版本号),它被构建和测试。也就是说,如果你有一个程序集使用另一个程序集的1.0.0.2版本的类型,它将(默认情况下)不使用相同的类型另一个程序集的版本1.0.0.4。这种使用名称和版本来标识引用的程序集有助于避免DLL Hell升级到其他应用程序的一个应用程序的问题。



问题:


  1. 为什么这样做?

  2. 如何使其不起作用?

  3. 奖金问题:在构建过程中会发生什么?外部依赖关系的版本不是硬编码为主要依赖关系吗?

请注意,Hello.dll没有被强烈命名



以下是HelloWorld.exe的清单:

  //元数据版本:v2.0.50727 
.assembly extern mscorlib
{
.publickeytoken =(B7 7A 5C 56 19 34 E0 89)// .z \V.4。
.ver 2:0:0:0
}
.assembly extern Hello
{
.ver 2:0:0:0
}
.assembly HelloWorld
{
... // snipped
}

这是从Fuslogvw.exe(汇编绑定日志查看器)中获取的汇编绑定日志:

  ===预绑定状态信息=== 
日志:User = ian.uy
日志:DisplayName = Hello,Version = 2.0.0.0,Culture = neutral,PublicKeyToken = null
(完全指定)
日志:Appbase = file:/// C:/Users/ian.uy/Desktop/HelloWorld/HelloWorld/bin/Debug/
日志:初始PrivatePath = NULL
日志:Dynamic Base = NULL
日志:Cache Base = NULL
日志:AppName = NULL
调用程序集:HelloWorld,Version = 1.0.0.0,Culture =公钥=空。
===
日志:此绑定在默认加载上下文中启动。
日志:找不到应用程序配置文件。
日志:使用C:\Windows\Microsoft.NET\Framework\v2.0.50727\config\machine.config中的机器配置文件。
日志:此时不适用于引用的策略(私有,自定义,部分或基于位置的程序集绑定)。
日志:尝试下载新的URL文件:/// C:/Users/ian.uy/Desktop/HelloWorld/HelloWorld/bin/Debug/Hello.DLL。
日志:装配下载成功。尝试设置文件:C:\Users\ian.uy\Desktop\HelloWorld\HelloWorld\bin\Debug\Hello.dll
LOG:输入源代码设置阶段。
日志:汇编名称为:Hello,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null
LOG:绑定成功。从C:\Users\ian.uy\Desktop\HelloWorld\HelloWorld\bin\Debug\Hello.dll返回程序集。
LOG:装配在默认加载上下文中。


解决方案



因为你已经指定了这个;)


如何使其不起作用?





  1. 右键单击解决方案资源管理器

  2. 选择属性

  3. 选择使用特定版本




奖金问题:在构建过程中会发生什么?外部依赖关系的版本不是硬编码为主要依赖关系吗?


除非你指定,否则。它是默认关闭。精心设计的组件应该向后兼容,版本不应该是真的重要。


I have two assemblies: HelloWorld.exe and Hello.dll. The exe is the main assembly and the dll is being used by the main assembly.

I compiled both HelloWorld.exe (1.0.0) and Hello.dll (1.0.0). I placed the assemblies on a different folder.

I then changed the version of Hello.dll to 2.0.0 and proceeded to overwrite the Hello.dll 1.0.0 with the 2.0.0 version. I then launch HelloWorld.exe and it worked fine.

I expected it to crash and burn immediately because the referenced Hello.dll when I compiled the EXE was 1.0.0. Now, the 1.0.0 DLL has been replaced by 2.0.0 but it still worked!

As per MSDN:

"By default, an assembly will only use types from the exact same assembly (name and version number) that it was built and tested with. That is, if you have an assembly that uses a type from version 1.0.0.2 of another assembly, it will (by default) not use the same type from version 1.0.0.4 of the other assembly. This use of both name and version to identify referenced assemblies helps avoid the "DLL Hell" problem of upgrades to one application breaking other applications."

Questions:

  1. Why did it work?
  2. How to make it NOT work?
  3. BONUS QUESTION: What happens during the build process? Isn't the version of external dependencies hard coded to the main dependency?

Note that Hello.dll is not strongly named.

Here's the manifest for HelloWorld.exe:

// Metadata version: v2.0.50727
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 2:0:0:0
}
.assembly extern Hello
{
  .ver 2:0:0:0
}
.assembly HelloWorld
{
...//snipped
}

Here's the Assembly Binding Log taken from Fuslogvw.exe (Assembly Binding Log Viewer):

=== Pre-bind state information ===
LOG: User = ian.uy
LOG: DisplayName = Hello, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
 (Fully-specified)
LOG: Appbase = file:///C:/Users/ian.uy/Desktop/HelloWorld/HelloWorld/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = NULL
Calling assembly : HelloWorld, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v2.0.50727\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Users/ian.uy/Desktop/HelloWorld/HelloWorld/bin/Debug/Hello.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\Users\ian.uy\Desktop\HelloWorld\HelloWorld\bin\Debug\Hello.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Hello, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
LOG: Binding succeeds. Returns assembly from C:\Users\ian.uy\Desktop\HelloWorld\HelloWorld\bin\Debug\Hello.dll.
LOG: Assembly is loaded in default load context.

解决方案

Why did it work?

Because you have specified so ;)

How to make it NOT work?

  1. Rightclick on the DLL in Solution Explorer
  2. Select Properties
  3. Select Use specific version

BONUS QUESTION: What happens during the build process? Isn't the version of external dependencies hard coded to the main dependency?

Not unless you specify so. It's off per default. Well designed assemblies should be backwards compatible and the version shouldn't really matter.

这篇关于装配加载版本不匹配:为什么加载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆