I'm loading an assembly at runtime and the question that arises everytime I call the code is that should I be checking if that particular assembly has loaded already? or does .Net take care of this and one assembly (same version) can only be loaded once? The basic question here is do i have to iterate through a list of loaded assemblies and see if my assembly was already loaded or not?
Thanks
To quote MSDN: "If an assembly with the same identity is already loaded, LoadFrom returns the loaded assembly even if a different path was specified. "
Related
After signing and recompiling a referenced assembly (MyAssembly.dll), my web application fails with "The located assembly's manifest definition with name MyReferencedAssembly does not match the assembly reference".
This is what I expected, since the PublicKeyToken has changed from null to a new key.
It seems you should be able to use an assemblyBinding section in the web.config file to make the application use the new signed assembly.
Problem is, there doesn't seem to be a way to identify the assembly the app will be looking for (the old, unsigned assembly) in the assemblyIdentity element.
Since the old publicKeyToken value was null, I've tried leaving it out, tried setting it to an empty string, null in quotes and none of them seem to work.
I've tried changing the version number so I can use binding Redirect from the old to the new version, and also tried setting a specific codeBase for the assembly.
All of this fails so I have to believe the assembly loading process just doesn't like loading a signed assembly when an unsigned one was referenced/expected.
How do I perform this mapping?
Recompiling the entire code base referencing the signed assemblies is not an option.
Thanks for any suggestions.
I'm building an application that will load untrusted assemblies for inspection (i.e. retrieval of the assembly full name). For security reasons, I'm trying to think of a way that these assemblies could be written that would allow them to execute code when loaded. I haven't code up with a method yet, but wanted to throw it out here to see if anyone could.
I'm aware that I could load these assemblies into an untrusted app domain, effectively stopping them from doing almost anything, but I wanted to avoid the complexity if it's un-needed.
Specifically, I will be calling Assembly.Load and <LoadedAssebmly>.FullName. Maybe there's a better way to load the assembly name without using the Assembly class?
Thanks,
Matt
First of all, there's the AssemblyName class. It allows you to find the assembly's name without loading it. Second, you can load assemblies using Assembly.ReflectionOnlyLoad, which uses the reflection-only context -- no code can be executed from such an assembly.
Yes, it is possible: .Net: Running code when assembly is loaded
I suggest, you use a method to inspect the assembly, that doesn't load it, i.e. Mono.Cecil
I had some code that referenced the Noesis.Javascript assembly (http://javascriptdotnet.codeplex.com) and had renamed the Noesis.Javascript.dll to Noesis.Javascript.0.4.dll. I referenced this file through Visual Studio, and when I launched my web app in the ASP.NET development server, I got this error:
Could not load file or assembly
'Noesis.Javascript.0.4' or one of its
dependencies. The located assembly's
manifest definition does not match the
assembly reference. (Exception from
HRESULT: 0x80131040)
I then tried to remove this reference and re-reference the older version of the library. I got the same error. I then tried to remove this reference entirely and comment out all code that used this library. I still get the same error. I have tried to explicitly close out the ASP.NET development server from its icon in the system tray, but this still occurs. I can find no reference of this assembly anywhere in my project now, yet the error persists. What might be happening? Is there some cache that I'm not finding? How can I resolve this error?
Go into the registry and set [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Refresh the page and the error output will show you which assembly has a dependency on Noesis.Javascript.0.4.
Check if "Noesis.Javascript.0.4" appears anywhere in your web.config file and remove it if it does. It might be in the <assemblies> part.
remove the reference and add it again. Please note that the two dll version must be same. Do not add any later version, if its get registered into your web.config, otherwise you need to remove from there too.
In my case, I added a wrong DLL. Instead of adding 64bit, I added 32bit.
Thanks,
I have a assembly made in another project (projA). Now I want to import this dll in another project (projB). How can I achieve this? This is what I've tried (in projB).
1 Put dll in same dir as my project. (the bin dir)
2 In web.config:
<assemblies>
<add assembly="projA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
This is the error I get:
Could not load file or assembly 'projA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
EDIT:
The point is that eventually the assembly reference must me added dynamically
EDIT 2:
The name of the assembly (and namespace) are stored in the database. The physical assembly (dll) is added (by installation) in projB. Now the code in projB must read the assembly name from the database and then add a reference to the dll which is added by installation.
Are all of projA's dependencies in projB? Usually I'd just add a reference from one project to another if they are in the same solution.
Edit:
If you want to add an assembly dynamically then maybe a service reference maybe something to consider. By dumping in projA's DLL into the bin that doesn't really give all the DLLs that it may require, thus there are ways to tie things together so that objects can be understood across systems, like web services using XML to give a common example.
My question back about adding an assembly dynamically is where would you get it from and can that part be automated to be part of projB as that is really the general solution to this kind of problem.
Edit 2:
How could you get all of projA's dependencies? Is it possible to get it so that it doesn't depend on a bunch of other DLLs that may or may not be on the system that this is to run. That is what the error is telling you, that there exists some assembly projC that is also required. Note that this adding of assemblies can continue for a long time if there are many levels of dependencies used.
Summarizing the answer: What would you need to reference in order to load projA into some new project? That's your problem which without knowing what the dependencies look like is rather hard to answer directly.
You do not need to add anything in Web.config if the assembly DLL is in the Bin folder - you only need to do this if you are referencing an assembly that is in the GAC.
The error message you are getting is basically saying that the assembly can't be found in the GAC, which is presumably because it isn't there!
You don't need to manually add the reference in the web.config file. Right click on your project in the Solution Explorer window in Visual Studio and select 'Add Reference'. Go to the Browse tab and find the DLL you created in the other project, select it and click OK. Optionally, you can add the project A to the same solution as project B and then add the reference through the Projects tab of the Add Reference window.
The error
The located assembly's manifest
definition does not match the assembly
reference.
suggests that a DLL was found but did not match the version, or public key.
I would suggest double checking to ensure that the assembly reference matches the version information and that no rogue DLL's with old version numbers are located in the /bin paths or the GAC
Well, I guess to some extent it depends on what you are planning on doing once you've loaded the assembly, and what you've got in the assembly.
I'll assume you've got some sort of plugin architecture, with a known interface or base class that you're going to be calling methods on, lets say IPlugin.
Anyway, here's how to load an assembly dynamically, based on storing a reference to it in either a config section or a DB column somewhere:
private IPlugin LoadPlugin(string fullTypeName) {
Type type = Type.GetType(fullTypeName, false, true);
Object plugin = Activator.CreateInstance(type);
if (plugin is IPlugin) {
return (IPlugin) plugin;
}
// Handle the fact you've not got what you expected however you like
throw new ApplicationException(error);
}
So this will take a string such as "projA.PluginClass, projA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" load the assembly, and return you an instance of the class you're interested in.
You would then use it like this:
// Call to DB to get details of class and assembly
string pluginClass = GetPluginDetails();
IPlugin plugin = LoadPlugin(pluginClass);
// Call known method to do something on IPlugin
plugin.SomeMethod();
I have a ASP.net application that is referencing a external assembly that I need to dynamically load and discover any types implementing a known interface. The problem I am having is that the type I reflect does not match the same interface that is running and so I cannot cast it.
Example:
This code is run in ASP.net app.
var assembly = Assembly.LoadFile(Path.Combine(HttpRuntime.BinDirectory, "ExternalAssembly.dll"));
var type = assembly.GetExportedTypes().First<Type>(x => x.Name == "AClass"); // AClass implements IAInterface
var reflectedInterface = type.GetInterface(typeof(IAmAInterface).ToString());
if (reflectedInterface != typeof(IAmAInterface))
throw new Exception("This makes me sad"); // This code gets run
The only difference I can see between the reflected interface I loaded from the bin and the interface returned from typeof is that the typeof assembly has a location in the temp ASP.net path (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\08c43c8b\3adac8cf\assembly\dl3\eb7a4127\0235ea60_a3c8c901\ReflectionTest.DLL)
Thanks Paul Alexander I have changed the code to use the Assembly.Load method not Assembly.LoadFile which solves the problem.
wwilden: I also tried extracting the interface into it's own assembly and this does also solve the problem.
When you use LoadFile the assembly is not loaded into the same context as your other assemblies at runtime so to the CLR interface runtime types are different. You can read more in Suzanne Cook's Debugging Assembly Load Failures.
If the assembly that you're loading is already in the Bin directory - you can load it by name. You don't need to know the exact path as the Bin folder is already in the assembly probing path.
Where is your interface type defined? Does it exist both in the reflected assembly as well as in the application itself? Then you actually have two different interfaces, even though they have the same namespace and name.
What you need to do is extract the interface from the reflected assembly and put it into another assembly that you refer to both from the reflected assembly as well as your application. Then it should work.
Apart from your problem, if you have a lot of assemblies to dynamically load, remember that they will remain in memory until the ASP.NET worker process reloads. This could influence your server's performance.
You could load the assemblies in a separate AppDomain (the smallest unit that is possible to unload), load a proxy class in that AppDomain which you reference with .NET remoting. Once finished, you unload the AppDomain.
There is an interesting article over at CodeProject about a situation like this. Where you have a class that has a structure that is identical with an interface without implementing the interface itself. The article outlines a method of dynamically creating wrapper classes that implement the needed interface. It could be helpful in your situation.