|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Why Assembly.Load get returns wrong assembly.I created a windows service with .NET 1.1 that is a shell that simply loads assemblies and then loads a certain type there and calls a method. Those dynamically loaded assmeblies meant to be upgardable. I wrote a code that replaced assemly files with the new version and then windows service supposed to load new version of the assembly and run it. Problem: While trying to implement this auto-upgrade feature, I ran into this sequence of events that leads to a strange result: - My windows service dynamically load an assembly "A" of version 1.0.1234.0000; run it for a while; - Then assmebly "A" dll file gets replaced with assembly "B" file of version 1.0.5678.000. - When service attempts to load assembly "B", for some reason returned reference points to assembly "A". I tried both Assemly.Load(AssembyName.GetAssemblyName(newAssemblyPath)) and Assembly.LoadFrom(newAssemblyPath) with the same result - both return reference to "A" of version 1.0.1234.000. Remarkably, AssembyName.GetAssemblyName(newAssemblyPath) returns correct AssemblyName object - the one for the new assembly "B". Then feeding this AssemblyName to Assemly.Load() still results in returned reference pointing to assembly "A". How to make sure Assemly.Load() and Assembly.LoadFrom() actually load the assembly I specify? Thank you, hi,
please check this link this may help you..... http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx thanks Show quote "Vlad Hrybok" wrote: > Background: > I created a windows service with .NET 1.1 that is a shell that simply loads > assemblies and then loads a certain type there and calls a method. Those > dynamically loaded assmeblies meant to be upgardable. I wrote a code that > replaced assemly files with the new version and then windows service supposed > to load new version of the assembly and run it. > > Problem: > While trying to implement this auto-upgrade feature, I ran into this > sequence of events that leads to a strange result: > - My windows service dynamically load an assembly "A" of version > 1.0.1234.0000; run it for a while; > - Then assmebly "A" dll file gets replaced with assembly "B" file of version > 1.0.5678.000. > - When service attempts to load assembly "B", for some reason returned > reference points to assembly "A". > > I tried both > Assemly.Load(AssembyName.GetAssemblyName(newAssemblyPath)) > and > Assembly.LoadFrom(newAssemblyPath) > with the same result - both return reference to "A" of version 1.0.1234.000. > Remarkably, AssembyName.GetAssemblyName(newAssemblyPath) returns correct > AssemblyName object - the one for the new assembly "B". Then feeding this > AssemblyName to Assemly.Load() still results in returned reference pointing > to assembly "A". > > How to make sure Assemly.Load() and Assembly.LoadFrom() actually load the > assembly I specify? > > Thank you, > -- > Vlad Hrybok > http://UltiDev.com Hello Vlad,
Problem is not in how to load assembly - how to unload them correctly. First, you can't unload specific assembly - only whole domain, thus u need to load your interchangeable asms into separate app domain. Second, when u use Assembly class to load asm it loads into the default domain. There is no way to unload asm from default domain without unload the whole app. I recommend u to look at App Domain class to realize loading asms into separate domains. VH> My windows service dynamically load an assembly "A" of version VH> 1.0.1234.0000; run it for a while; VH> - Then assmebly "A" dll file gets replaced with assembly "B" file of VH> version VH> 1.0.5678.000. VH> - When service attempts to load assembly "B", for some reason VH> returned VH> reference points to assembly "A". VH> I tried both VH> Assemly.Load(AssembyName.GetAssemblyName(newAssemblyPath)) VH> and VH> Assembly.LoadFrom(newAssemblyPath) --- WBR, Michael Nemtsev :: blog: http://spaces.live.com/laflour "At times one remains faithful to a cause only because its opponents do not cease to be insipid." (c) Friedrich Nietzsche Hi Vlad,
Based on my understanding, your .Net Windows Serivce applicaion wanted to support auto-updating function for some assemblies, so that the administrators/users can replace the new version of assembly without stopping the Windows Service. If I have misunderstood you, please feel free to tell me, thanks. When a .Net application loads an assembly into the memory, this on-disk assembly will be locked by the system. So can you tell me how do you replace the same assembly with the new version? Do you changed the assembly name so that it will not "replace" the old assembly, but just being added into certain directory? I hope you can explain your updating logic more clear. This will help us identify your problem better. Thanks. If you wanted to explicitly load the assembly B whatever, you should use Assembly.LoadFrom. Note: you should pass the pathname to the method *with* the file extension. Also, you should not provide the strong-name information, that is, the string can't contain version, culture, or public key information. Once you obey these rules, you should can load the extra assembly B without any problem. Finally, as "Michael Nemtsev" has pointed out, although can you load the new version of assembly, the old version of assembly can not be unloaded, if you are using single AppDomain. This is because we can not unload an assembly from an AppDomain, however, we can unload an AppDomain explicitly. So the recommended solution to implement auto assembly updating is using more than 1 AppDomain. There are several key points to implement the solution: 1. Since the old version will be locked by the system, you should ShadowCopyFiles property to shadow copy the old version of assembly. By donig this, the runtime will copy the assembly to a cache directory, and then open that one. That leaves the original file unlocked, and gives us the ability to update an assembly that's in use. ASP.NET uses this facility. 2. You may use FileSystemWatcher class to monitor the assembly directory so that whenever the new version assembly is replacing the old one, your application will be notified with events. 3. Creating a new AppDomain to load the assembly so that while updating, you can unload the entire AppDomain and create a new AppDomain to load the new version. There is a MSDN article demonstrating this technology: "AppDomains and Dynamic Loading" http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp05162002.asp 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#notifications. 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. Thanks to all who replied. I ended up using AppDomain, which allowed me to
achieve desired result. A couple of things worth mentioning: - Countrary to what I expected and what Jeffrey described, my dynamically-loaded assemlies were not locked. I had no problem deleting them even though they were loaded. I don't know if that has to do with late binding, but with and without AppDomain, replacing assemblies was straightforward. - Prior to using AppDomain I tried both Assembly.Load and Assembly.LoadFrom in all their forms with the same strange result - returned Assembly reference was pointing to the old version of the assembly. Whatever the rules that make such behavior valid, they are not intuitive at all. Hi Vlad,
#1, it is interesting that the file is not locked when you are using Assembly.Load to load it into memory. Based on my experience, the loader will always place a lock on the assembly file. #2, I am not sure why Assembly.LoadFrom does not work in your application. Is it possible for you to create a little sample project to demonstrate the problem? Then I will help you to troubleshoot the root cause. Additionally, since .Net CLR uses fusion to lookup the assembly, you may use Fuslogvw.exe(Assembly Binding Log Viewer) to examine the Assembly.LoadFrom() probing path. The log may reveal more information about the failure. 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. Thanks, Jeffrey.
I probably won't bother trying to reproduce Assembly.Load issue - using AppDomain solved the issue and even though I would love to get to the bottom of it, my schedule is too tight - I spent more time working on assembly upgradeability feature than I thought I would. My only complaint is that it was hard to find the problem because I expected Assembly.Load to throw an exception if specified assembly didn't get loaded for some reason, instead of quiely returning the reference to another assembly. Thanks again, Hi Vlad,
Thanks for your feedback. Yes, I understand that. Schedule sometimes forbids us to go deeper to find out the root cause. I was also surprised to find that Assembly.Load/Assembly.LoadFrom methodes do not work in your application, since I have tried the similar approach several times in other applications. And I always use Fuslogvw.exe to check the problem. Sorry, without reproducing this strange behavior on my side, I can not provide more information for the root cause of this problem. Thanks for your understanding. Anyway, I think your current solution of using AppDomain is a good one, since it allows you to unload the old version of assemblies from memory, while the old approach can not get this done. I recommend you go with this AppDomain solution. If you need help on this issue when you have time, please feel free to post, I will work with you. 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. Thanks, Jeffrey. I appreciate your help.
I have tripped again on what seems to be another protuberance of LoadFrom()
issue: Visual Studio setup/MSI projects won't work correctly in upgrade mode if you have cusom actions done using .NET installer classes. According to http://support.microsoft.com/kb/906766 LoadFrom() can't tell old custom action assembly from the new one despite them being in differrent locations. I tried signing/strong-naming the assmbly but still have issues in upgrade mode. Show quote > Hi Vlad, > > #1, it is interesting that the file is not locked when you are using > Assembly.Load to load it into memory. Based on my experience, the loader > will always place a lock on the assembly file. > > #2, I am not sure why Assembly.LoadFrom does not work in your application. > Is it possible for you to create a little sample project to demonstrate the > problem? Then I will help you to troubleshoot the root cause. > > Additionally, since .Net CLR uses fusion to lookup the assembly, you may > use Fuslogvw.exe(Assembly Binding Log Viewer) to examine the > Assembly.LoadFrom() probing path. The log may reveal more information about > the failure. > > 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. > > Hello Vlad,
From your description, you have an VS 2005 built setup program that has new version which will uprade the original installed application. However, you encountered the following issue and can not get it work through the workaround provided in it, correct? http://support.microsoft.com/kb/906766 For the assembly signing, are you perform the strong-name signing on your custom assembly? I suggest you use the Fuslogvw.exe utility to trace the assembly binding to see how did the MSI setup program look for the custom action assembly,(check whether the assembly identifier contains the assembly name you've strong-named). also, if possible, can you produce a simplified dummy setup program to demonstrate the behavior you met? Then, I'll be able to perform some local tests against it. Sincerely, Steven Cheng Microsoft MSDN Online Support Lead This posting is provided "AS IS" with no warranties, and confers no rights. I was able to establish that my "real" setup project acts as if the custom
action assembly was not signed: it keeps launching custom steps from previous version unless I give the assembly name that is differrent from the previous version, which is not acceptable in my case. In simple test setup case signing did solve the problem. I could send MSI files with both old and new versions so you could see yourself that custom actions assembly and all its dependencies are indeed signed. Show quote "Steven Cheng[MSFT]" wrote: > Hello Vlad, > > From your description, you have an VS 2005 built setup program that has new > version which will uprade the original installed application. However, you > encountered the following issue and can not get it work through the > workaround provided in it, correct? > > http://support.microsoft.com/kb/906766 > > For the assembly signing, are you perform the strong-name signing on your > custom assembly? I suggest you use the Fuslogvw.exe utility to trace the > assembly binding to see how did the MSI setup program look for the custom > action assembly,(check whether the assembly identifier contains the > assembly name you've strong-named). > > also, if possible, can you produce a simplified dummy setup program to > demonstrate the behavior you met? Then, I'll be able to perform some local > tests against it. > > Sincerely, > > Steven Cheng > > Microsoft MSDN Online Support Lead > > > This posting is provided "AS IS" with no warranties, and confers no rights. > > Thanks for your reply Vlad,
Yes, as you mentioned that the siging approach does work in simple test case and that confirms to what I've researched. So far I think the problem should be specific to the particular custom action and dependencies of your setup program. Due to the complexity of this scenario, I would suggest you consider contacting CSS for further troubleshooting on this. And you can reference the kb article to the product support engineer to confirm whether this does be an know issue that violate the documented behavior. http://msdn.microsoft.com/subscriptions/support/default.aspx Sincerely, Steven Cheng Microsoft MSDN Online Support Lead This posting is provided "AS IS" with no warranties, and confers no rights. |
|||||||||||||||||||||||