.NET Forum / .NET Framework / CLR / November 2006
Side-By-Side Assembly Loading -- Same App Domain -- 2 versions of same Assembly
|
|
Thread rating:  |
Howard Hoffman - 20 Oct 2006 15:05 GMT I have an ASP.NET application that uses an assembly 'A'. 'A' is strongly named, culture-neutral and is at version 1.1.2.444. I have another assembly 'P' that is built against version 1.2.3.22 of assembly 'A'.
Is it possible for me to dynamically load assembly 'P' in my application such that all 'P's references to 'A' hit version 1.2.3.22, but the original application's calls into 'A' hit veresion 1.1.2.444?
There is only one app domain for the application. The thing is that 'P' is a plug-in that is written many months after 'application' is released.
Seems like this is the kind of thing we should be able to do in .NET, but I can't get it to work.
My application bin directory has 'A', version 1.1.2.444 in it. The 'P' assembly is located in bin\p (where 'p' is the assembly-name) and that subdirectory also contains the newer version of 'A'. So, there are 2 copies of 'A' on disk -- one in bin, and one in bin\p.
I'm getting Fusion errors when I try to load (via AppDomain.CurrentDomain.CreateInstanceAndUnwrap(string, string)) 'P', saying it cannot find version 1.2.3.22 of 'A'.
I've tried adding <runtime><assemblyBinding><dependentAssembly> naming version 1.2.3.22 of 'A', as well as adding <runtime><probing> naming the 'bin\p' path. Neither has solved the problem -- the Fusion dump (in the error page) doesn't show it hitting 'bin\p' in any of the cases.
Am I missing something obvious?
Thanks in advance,
Howard Hoffman
Ben Voigt - 20 Oct 2006 16:29 GMT >I have an ASP.NET application that uses an assembly 'A'. 'A' is strongly >named, culture-neutral and is at version 1.1.2.444. [quoted text clipped - 4 lines] > such that all 'P's references to 'A' hit version 1.2.3.22, but the > original application's calls into 'A' hit veresion 1.1.2.444? Are any instances of objects from 'A' passed between the main application and P?
Howard Hoffman - 20 Oct 2006 17:33 GMT No instance of 'A' are passed between the main app and P. However, both 'P' and the main App use instances from 'A' internally.
>>I have an ASP.NET application that uses an assembly 'A'. 'A' is strongly >>named, culture-neutral and is at version 1.1.2.444. [quoted text clipped - 7 lines] > Are any instances of objects from 'A' passed between the main application > and P? Jeffrey Tan[MSFT] - 23 Oct 2006 07:52 GMT Hi Howard,
Yes, what you want can be achieved in .Net. This is called Side-By-Side execution.
I have written 3 sample test projects to demonstrate your situation: SxSTest, AddinPrj and ClassLibrary1. The SxSTest is a winform application for simplicity which uses the 1.0.0.0 version of ClassLibrary1. AddinPrj is the Addin project that uses the 2.0.0.0 version of ClassLibrary1. Below is the test code:
//ClassLibrary1 version 1.0.0.0 namespace ClassLibrary1 { public class Class1 { public static int StaticMethod(int a, int b) { return a+b; } } }
//ClassLibrary1 version 2.0.0.0 namespace ClassLibrary1 { public class Class1 { public static int StaticMethod(int a, int b) { return a*b; } } }
//AddinPrj project namespace AddinPrj { public class AddIn { public static int AddInMethod() { return ClassLibrary1.Class1.StaticMethod(5, 6); } } }
//SxSTest private void button1_Click(object sender, System.EventArgs e) { MessageBox.Show(ClassLibrary1.Class1.StaticMethod(5, 6).ToString()); }
private void button2_Click(object sender, System.EventArgs e) { MessageBox.Show(AddinPrj.AddIn.AddInMethod().ToString()); } I placed the 1.0.0.0 and 2.0.0.0 version of ClassLibrary1 in "V1" and "V2" subdirectory of the Exe bin folder.
During the testing, I found that the Probing privatePath can not be used to notify the runtime to load the assembies with the same name. We should use the <codeBase> element to configure the runtime the correct loading path. For example, in my test scenario, the below app.config file works for me: <?xml version="1.0" encoding="utf-8" ?> <configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="ClassLibrary1" publicKeyToken="270aa85ff6943c10" /> <codeBase version="1.0.0.0" href="V1/ClassLibrary1.dll"/> <codeBase version="2.0.0.0" href="V2/ClassLibrary1.dll"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
So you may add the same syntax of <codeBase> to your Asp.net application's web.config file, the runtime will happily load the 2 different versions of assembly 'A'. I have tested above code under both .Net1.1 and .Net2.0, if it still does not work for you, please feel free to tell me, thanks.
Finally, below is the official document regarding how the runtime locates the assemblies. Please note the "Multiple Assemblies with the Same Name" section, it means "multiple assemblies with the same name" should use <codeBase> as the configuration element. http://msdn2.microsoft.com/en-us/library/15hyw9x3.aspx
Hope this helps.
Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Howard Hoffman - 23 Oct 2006 19:02 GMT Jeffrey -
Thanks for the tip. I didn't think to try 2 different <codeBase> elements in the <dependencyAssembly> element. However, I'm still stuck.
This is my web.config now:
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="ClassLibrary1" publicKeyToken="a40ccc8d88606ee3" culture="neutral" /> <codeBase version="1.3.1.200" href="BiggerClassLibrary/ClassLibrary1.dll"/> <codeBase version="0.9.1.65534" href="ClassLibrary1.dll" /> </dependentAssembly> </assemblyBinding> </runtime>
The web application's "bin" directory has a subdirectory named "BiggerClassLibrary" which contains the file "ClassLibrary1.dll", as well as all the other files that are build when we build "BiggerClassLibrary". I used Relector to copy/paste the public key token, and it is correct.
ClassLibrary1 is in 2 places -- the web application's "bin" directory and the "BiggerClassLibrary" subdirectory under bin.
Maybe this is significant: ClassLibrary1 contains a ConfigurationSection subclass that BiggerClassLibrary specializes. There is a section, elsewhere in web.config, that contains the configuration for BiggerClassLibrary. So, to be clear, I've this :
<configuration> <configSections> <sectionName = "BiggerLibrary" type="BiggerClassLibraryConfig, BiggerClassLibrary"> ... </configSections> <runtime> .. as above </runtime> ... <BiggerLibrary ... /> </configuration>
If the regular ConfigurationSection loader stuff uses dynamic loading which itself uses the <assemblyBinding> configuration to find assemblies, then this shouldn't matter, right?
If I turn on the Fusion Registry entry, shouldn't I see the BiggerClassLibrary directory added to the list of places searched? I do not see it.
I get an error creating the configuration section handler -- that handler is in BiggerClassLibrary -- saying that it could not load ClassLibrary1 v 1.3.1.200 or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT 0x80131040).
Any more suggestions?
Howard
> Hi Howard, > [quoted text clipped - 111 lines] > This posting is provided "AS IS" with no warranties, and confers no > rights. Jeffrey Tan[MSFT] - 26 Oct 2006 06:56 GMT Hi Howard,
How about this issue now? Have you managed to create a sample project to demonstrate this problem and the fusion log? Is your problem resolved? Please feel free to feedback the issue status and your concern, thanks.
Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Abhishek Singh - 01 Nov 2006 08:19 GMT Howard,
If <codebase> is not working then you can install either/both versions into GAC(agreed, GAC should be used only when Applications need to share DLLs, but with GAC having support for Reference count while unistalling; using GAC in this case is not that bad..)
Jeffrey,
I tried Side-by-Side execution, and surprised by the behavior of .NET framework. I am not able to understand how can this work?
This is what i have done: 1. App.Exe built with version 2.0 2. Library1 built with version 2.0 3 Library2 built with version 1.0
Now App.exe invokes a function on Library1, which returns an object of version 2.0.
Now app.exe passes this object(2.0) to library2(built with 1.0). Then library2 performs some action on this object.
The strange thing is that for library2(built with 1.0), the passed object appears to be just a 1.0 object, although the object was generated from 2.0 version. Infact it is even to call those functions in 1.0, which were removed in 2.0
I checked the reference of the object has not changed.
SO i am in doubt how, version 2.0 object appears as an 1.0 object???
Any idea, what's going behind the scene.
Regards,
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|