.NET Forum / .NET Framework / .NET SDK / July 2007
LoadAssembly, GetType - can't find reference
|
|
Thread rating:  |
David Thielen - 17 Jul 2007 18:26 GMT Hi;
I am trying to create an object from a dynamically loaded assembly. This dynamically loaded assembly has a reference to a dll that the loading program also has.
Trying to debug it I call: Assembly a.s = Assembly.LoadFile(parts[0]); object obj = a.s.GetExportedTypes();
And the call to GetExportedTypes() throws an exception saying it cannot find the referenced dll WindwardReports.dll - which is also referenced by the code making this call.
This is in a Word AddIn.
Any ideas?
 Signature thanks - dave david_at_windward_dot_net http://www.windwardreports.com
Cubicle Wars - http://www.windwardreports.com/film.htm
Walter Wang [MSFT] - 18 Jul 2007 02:25 GMT Hi Dave,
I suggest first to use fusion log viewer (http://blogs.msdn.com/junfeng/archive/2004/02/14/72912.aspx) to get detailed error.
I cannot seem to reproduce the issue using a console application and two class libraries. Can you tell me more about the configuration such as are the assemblies strong named, where are they located? Of course it would be great if you could send me a reproducible project to test.
Regards, Walter Wang (wawang@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
David Thielen - 18 Jul 2007 17:34 GMT Hi;
Found the problem. The log shows: 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:/Program Files/Microsoft Office/OFFICE12/AutoSizeBean.DLL. LOG: Attempting download of new URL file:///C:/Program Files/Microsoft Office/OFFICE12/AutoSizeBean/AutoSizeBean.DLL. LOG: Attempting download of new URL file:///C:/Program Files/Microsoft Office/OFFICE12/AutoSizeBean.EXE. LOG: Attempting download of new URL file:///C:/Program Files/Microsoft Office/OFFICE12/AutoSizeBean/AutoSizeBean.EXE. LOG: All probing URLs attempted and failed.
However, I load the assembly using: string filename = Path.GetFullPath(parts[0]); Assembly a.s = Assembly.LoadFile(filename); object obj = a.s.GetTypes();
where filename points to the dll file - which is in a different directory. And LoadFile() returns an object. So why is it not looking in the directory where the file is?
 Signature thanks - dave david_at_windward_dot_net http://www.windwardreports.com
Cubicle Wars - http://www.windwardreports.com/film.htm
> Hi Dave, > [quoted text clipped - 17 lines] > > This posting is provided "AS IS" with no warranties, and confers no rights. Walter Wang [MSFT] - 20 Jul 2007 11:05 GMT Hi Dave,
Sorry for delayed reply, I was not in office yesterday.
Is it a full path or just the file name?
The log seems normal, that's how fusion loads a private assembly (not in GAC), it will try with the assembly name and a subdirectory with the same name, also extension will be tried with DLL and EXE.
Can you tell me more about your assembly's naming and location? Do you have duplicated copies?
Regards, Walter Wang (wawang@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
David Thielen - 20 Jul 2007 16:58 GMT It gives the full filename. I even call Patg.GetFullName() on it to make sure it is the full name.
 Signature thanks - dave david_at_windward_dot_net http://www.windwardreports.com
Cubicle Wars - http://www.windwardreports.com/film.htm
> Hi Dave, > [quoted text clipped - 19 lines] > > This posting is provided "AS IS" with no warranties, and confers no rights. Walter Wang [MSFT] - 23 Jul 2007 06:45 GMT Hi Dave,
What I meant is that what's the correct complete full path? Fusion tried with C:/Program Files/Microsoft Office/OFFICE12/AutoSizeBean.DLL, but this is apparently not correct, right?
Could you please tell me more about the scenario to help me reproduce the issue on my side?
Regards, Walter Wang (wawang@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
David Thielen - 23 Jul 2007 15:50 GMT Hi;
I am calling: Assembly a.s = Assembly.LoadFile("c:\\src\\kahuna\\AutoTag\\AutoTagCore\\bin\\debug\\AutoSizeBean.dll"); object obj = a.s.GetExportedTypes();
So it is getting the full path. But it never looks there.
 Signature thanks - dave david_at_windward_dot_net http://www.windwardreports.com
Cubicle Wars - http://www.windwardreports.com/film.htm
> Hi Dave, > [quoted text clipped - 15 lines] > > This posting is provided "AS IS" with no warranties, and confers no rights. Walter Wang [MSFT] - 24 Jul 2007 13:30 GMT Hi Dave,
This is my understanding of your configuration so far:
<your main app dir>\ <your addin>.dll WindWardReports.dll
c:\src\kahuna\AutoTag\AutoTagCore\bin\debug\ AutoSizeBean.dll WindWardReports.dll
And from <your addin>.dll, you're trying to call LoadFile("c:\src\kahuna\AutoTag\AutoTagCore\bin\debug\AutoSizeBean.dll"), the loading is successfully, but if you call the returned Assembly.GetExportedTypes(), .NET reports error that it cannot find "WindWardReports.dll".
I created a test solution locally which includes three projects:
* ConsoleApplication1, references ClassLibrary1 * ClassLibrary1 * ClassLibrary2, references ClassLibrary1
In ConsoleApplication1, I used an absolute path to call LoadFile("...ClassLibrary2.dll"), this works correctly and the GetExportedTypes() also runs correctly. In this case, the fusion log also shows it tries to load ClassLibrary2 from the directory where ConsoleApplication1.exe resides, this seems can be ignored since the ClassLibrary2.dll is loaded successfully.
Basically I'm saying that I cannot reproduce the issue you mentioned, can you create a reproducible project on your side and send it to me? Thanks.
Regards, Walter Wang (wawang@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
David Thielen - 25 Jul 2007 06:52 GMT Hi;
Not exactly. It is a Word AddIn in C# (IExtensibility, not VSTO) and that dll tries to load the other dll. I have a small sample but I have to go home now so I will not be able to get it bundled up and emailed to you until tomorrow.
But the problem appears to be trying to do this in a Word AddIn. Word may be causing the problem.
 Signature thanks - dave david_at_windward_dot_net http://www.windwardreports.com
Cubicle Wars - http://www.windwardreports.com/film.htm
> Hi Dave, > [quoted text clipped - 40 lines] > > This posting is provided "AS IS" with no warranties, and confers no rights. David Thielen - 26 Jul 2007 05:48 GMT Hi;
I wrote a small test program - and it works fine. Obviously there is a difference but I have no idea what.
Any idea what would cause it not to look in the file an assembly is created from for the types in that assembly? It's the Assembly.GetTypes() that is failing after it returns a good object on Assembly.LoadFile().
One thing I did not duplicate in the sample program - I am calling this in an event handler. Is it possible the event handler is in a Word thread rather than that of my AddIn? And if so, how do I get it back to my AddIn's thread? It is all the code I am calling in the event handler the Assembly.LoadFile() and Assembly.GetTypes().
 Signature thanks - dave david_at_windward_dot_net http://www.windwardreports.com
Cubicle Wars - http://www.windwardreports.com/film.htm
> Hi Dave, > [quoted text clipped - 40 lines] > > This posting is provided "AS IS" with no warranties, and confers no rights. Walter Wang [MSFT] - 26 Jul 2007 11:17 GMT Hi Dave,
I've downloaded the test project and found it's throwing the exception when I call a.s.GetTypes() as your described. However, if you look into the exception, .NET is trying to load WindwardReports.dll from GAC instead of the private copy. After I intalled the WindwardReports.dll into GAC, the type loads successfully. (Your C# test project isn't referening the assembly, that's why it succeeds)
To see if this is the issue of Word add-in, I created a local word add-in for test but it seems a simple strong named assembly doesn't reproduce the issue. I think this might be related how WindwardReports.dll is built, could you please depict more?
Regards, Walter Wang (wawang@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
David Thielen - 26 Jul 2007 15:28 GMT For my real case (not the test case), the program loading the dll has already made a call to WindwardReports.dll so WindwardReports.dll is already loaded - why is it not finding it?
 Signature thanks - dave david_at_windward_dot_net http://www.windwardreports.com
Cubicle Wars - http://www.windwardreports.com/film.htm
> Hi Dave, > [quoted text clipped - 20 lines] > > This posting is provided "AS IS" with no warranties, and confers no rights. Walter Wang [MSFT] - 30 Jul 2007 06:48 GMT Hi Dave,
I've done some further research and I think I've found the root cause now.
Per the documentation of LoadFile:
<quote> Use the LoadFile method to load and examine assemblies that have the same identity, but are located in different paths. LoadFile does not load files into the LoadFrom context, and does not resolve dependencies using the load path, as the LoadFrom method does. LoadFile is useful in this limited scenario because LoadFrom cannot be used to load assemblies that have the same identities but different paths; it will load only the first such assembly. </quote>
Two points here:
1) LoadFile does not resolve dependencies using the load path.
Therefore, if we call LoadFile("<path>\ClassLibrary2.dll") which references ClassLibrary1.dll, it will not use the path of ClassLibrary2.dll to load ClassLibrary1.dll. Instead, it will look in current AppDomain's loaded assemblies list first, it not found, then it will try to load from GAC. (This is why I found previously that adding your WindwardReports.dll to GAC will succeed)
2) LoadFile does not load files into the LoadFrom context.
This means assembly loaded with LoadFile cannot be used by furthre LoadFile calls. In other words, if we call LoadFile("<path>\ClassLibrary1.dll") first, then call LoadFile("<path>\ClassLibrary2.dll"), it still cannot find ClassLibrary1.dll since it's not loaded into the context. However, if we "Add Reference" to ClassLibrary1.dll first in the main application, then further call to LoadFile("<path>\ClassLibrary2.dll") will succeed since the assembly is already in the context. (This is why my test project fail to reproduce the issue on the very beginning: since you mentioned that the add-in is using the shared assembly, so my test project added a reference to ClassLibrary1.dll in the main application.)
Therefore, the fix to your issue is to use LoadFrom instead of LoadFile. However, LoadFrom will only load an assembly if it's not already loaded. Following code will demostrate the point:
Assembly ass1 = Assembly.LoadFrom(@"c:\test\ClassLibrary1\bin\x86\Debug\ClassLibrary1.dll"); Console.WriteLine(ass1.CodeBase); Assembly ass2 = Assembly.LoadFrom(@"c:\test\ClassLibrary2\bin\x86\Debug\ClassLibrary1.dll"); Console.WriteLine(ass2.CodeBase);
Above code will both print out "c:\test\ClassLibrary1\bin\x86\debug\ClassLibrary1.dll", second call to LoadFrom will not load it again from a second place. This is the case "assemblies that have the same identities but with different paths".
Hope this helps.
Regards, Walter Wang (wawang@online.microsoft.com, remove 'online.') Microsoft Online Community Support
================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
David Thielen - 30 Jul 2007 16:14 GMT Bingo - that all makes sense now. Thanks for digging in to this.
 Signature thanks - dave david_at_windward_dot_net http://www.windwardreports.com
Cubicle Wars - http://www.windwardreports.com/film.htm
> Hi Dave, > [quoted text clipped - 64 lines] > > This posting is provided "AS IS" with no warranties, and confers no rights. David Thielen - 26 Jul 2007 05:52 GMT Got it!
Sample here - http://www.windwardreports.com/temp/LoadAssembly.zip
It fails if the bean is a J# dll. Works fine for a C# dll. Any ideas?
 Signature thanks - dave david_at_windward_dot_net http://www.windwardreports.com
Cubicle Wars - http://www.windwardreports.com/film.htm
> Hi Dave, > [quoted text clipped - 40 lines] > > This posting is provided "AS IS" with no warranties, and confers no rights. David Thielen - 27 Jul 2007 18:46 GMT Ok, I have a sample with the problem at http://www.windwardreports.com/temp/TestLoadAssembly.zip
The issue seems to be if there is a 4th dll with the interface definition. Even if you put the InterfaceLib as a reference to MyEngine it still does not find it.
 Signature thanks - dave david_at_windward_dot_net http://www.windwardreports.com
Cubicle Wars - http://www.windwardreports.com/film.htm
> Hi Dave, > [quoted text clipped - 17 lines] > > This posting is provided "AS IS" with no warranties, and confers no rights.
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 ...
|
|
|