I posted a similar question a time ago. I need to load an assembly at runtime.
This is easy if I know the absolute path of the dll at runtime.
But I dont :( The assembly.Load() or LoadFromFile() fails if the file is not in the application root.
The only thing I have is the dll name. The dll could be located in the root, system32 or in even in the GAC.
Is it possible for .net to automatically determine where the dll is at, like for example :
it should first look in the root. If its not there move on to the system folders, else try the GAC.
EDITED
I am using plug-in architecture. I do not need to register the dll. I have a multi user application. I have a applications table containing information regarding applications. Each application has a dll path associated with it, containing certain algorithms associated with that app. Hope this helps.
I hope you've read up on the following. My suggestion...
How the runtime locates assemblies
You can give Assembly.LoadWithPartialName a whirl.. might work.. it says it will search the application folder and the GAC unlike Assembly.Load. (However its less safe.. coz you might end up with the wrong version of the DLL since you dont specify all 4 parts of the Assembly Name)
Also try AppDomainSetup.PrivateBinPath (AppDomain.AppendPrivatePath has been deprecated in favor of this) to add subfolders of the application root to the list of folders to probe assemblies for. You can also try copying over files from other places into a [AppFolder]\MySandboxForDLLsToLoad, which is added to the PrivateBinPath.
When the current application looks for assemblies, it looks in several locations (bin folder, gac, etc..) if it can not find one, then the developer needs to manually tell the application where to look. You can do this by intercepting the AssemblyResolve event, and using the event args to tell the CLR where your assembly is.
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
....................
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var strTempAssmbPath=
Path.GetFullPath("C:\\Windows\\System32\\" + args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll");
var strTempAssmbPath2=
Path.GetFullPath("C:\\Windows\\" + args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll");
if (File.Exists(strTempAssmbPath))
return Assembly.LoadFrom(strTempAssmbPath);
if (File.Exists(strTempAssmbPath2))
return Assembly.LoadFrom(strTempAssmbPath2);
}
You can hook up into AppDomain.CurrentDomain.AssemblyResolve event and load the assembly for your application manually on demand.
Yes there is a way and it depends on whether your dll is weakly(without a public key token) or strongly(with a public key token) named. If its weakly named and you have added a reference to the assembly with the dll within VS, then VS will first look in the application folder root and if it does not find it, it will then look in the subdirectories that you specify as the value of the privatePath attribute in your XML config file.
If its a strongly named dll, then the CLR will search in the GAC so you need to install the dll in the GAC. The CLR can also look in the application directory if you install an XML config file that has its codeBase element pointing to the dll's path.
To specify an assembly in the GAC you can use the /reference:[DLL name] switch when compiling your assembly.
The dll will be found automatically is it is in some location referenced in the PATH system variable (i.e., system32) or if the dll is registered. You can't find it if it can be anywhere on disk, but no one needs that functionality anyway.
EDIT: can the dll's be registered? how are you getting the assembly name if you don't know of the assembly ahead of time? Are you creating some type of plug-in architecture? I think it would help if you explained your situation a bit more.
EDIT2: If that is the case, why not provide a way for the user to register his or her plug in? You can get all the information that you need from an open file dialog. That or simply make them dump it into a folder that you specify.
You have three options
Install the assembly in the global assembly cache (GAC)
Use an application configuration (.config) file with the tags
Use the AssemblyResolve event
You can find the details here.
The resolution algorithm used by .NET to find the assemblies and their dependents is straight forward.
.NET identifies the required version. Usually the information about the dependant assemblies is present in the application's assembly manifest.
.NET searches GAC (Global Assembly Cache), only if the assembly is strong named.
If not found in GAC, and if a .config file presnt, then .NET searches the location specified in the cofiguration file, else .NET searches directory containing the executable (.EXE)
After this, If the assembly is still not found, the application terminates with error.
Click here for the video explaining the .net resolution algorithm, and click here for a video on late binding assemblies
Register this assembly into the GAC. How to do that
Use this
Assembly.LoadWithPartialName(assemblyName);
Related
I currently have a .NET application which references "SomePackage.dll" and "SomeUtilities.dll".
SomePackage.dll is contained in a separate folder, and one of the assemblies it depends on is also named "SomeUtilities.dll".
In other words, I added a reference in my project to \somePath\SomePackage.dll, and there exists a file \somePath\SomeUtilities.dll that SomePackage.dll depends on. Since I already have a reference in my project to a assembly called SomeUtilties.dll, I could not add a reference to \somePath\SomeUtilties.dll.
As a result, when I try to run my application and initialize a module in from SomePackage.dll, I receive an error:
Could not load file or assembly 'SomeUtilities.dll..." or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.'
To work around this, I used gacutil in the VS developer command prompt to add \somePath\SomeUtilities.dll to the GAC. Now both assemblies are resolved fine, but I was wondering if there was a better way to resolve this name collision that doesn't involve adding to the GAC. I'm worried about potential issues that may arise with installing into the GAC, and have heard that .NET has the ability to look through certain subfolders to resolve assemblies, but am not sure where to find more on this concept.
You can use bind redirect.
Open the .config file to find the location of < assemblyBinding>
Remove the < assemblyBinding> reference.
Type in Package Manager Console: Add-BindingRedirect.
Windows/.NET has a tool called FUSLOGVW.exe that will help find issues with assemblies. This tool is useful but sifting through the logs is cumbersome. There is an open source tool that is a wrapper around FUSLOGVW.exe and makes it much easier to sift through the data and find the root of the problem. I would use this
https://github.com/awaescher/Fusion
I have a solution that includes several projects. A few are libs that are building dll's used in my main project in this solution.
My main project builds with output type console application.
This all works fine.
When i change the build output type to a class library (since i want to use this project as a plugin eventually). The project will still build, this time to a dll.
When i use this plugin in an application where i use it as a dll however, it will run up to a certain point where it's trying to load a type defined in an external dll (so NOT built by my solution) and throw the exception:
Could not load type 'externalinterface' from assembly 'externallib, version=3.0.0.0, Culture=neutral, PublicKeyToken=null'.
The dll's are all in the correct folder,etc.
Also worth noting, the plugin is tested in another location than where i built it. The executable still works on this location, the dll/plugin does not. Same amount of dll's in their folders etc.
EDIT: I already used ILSpy (dll inspector) to open the actual dll that is being referenced (so externallib in the errormessage) and checked if 'externalinterface' was present and it is.
EDIT2: RESOLVED! The program that loaded my plugin was loading the same dll that caused the exception. The dll it loaded was of another version than the one i loaded.
Check whether the type externalinterface is present in the referred dll.
You didn't include the details of the exception the application is throwing. However, based on the message you gave, it appears your assembly does not have a strong name. If the application attempting to load your assembly as a plugin does have a strong name, then .NET will require all assemblies loaded by it also have a strong name, so you need to configure your assembly to have a strong name before continuing.
Maybe some supported dll's which is used by the 'externalinterface' is missing in the target machine. In the target machine, check is all the necessary dll's are present in the output folder.
Or blindly copy paste all the dlls in the output folder from the machine where the code is working to the target machine where you have the problem. After this, if the code is working in the target machine, then try to analyze which supporting dll you are missed to copy.
This is strange...
In a project of mine I need to load external dll's at runtime. I've done this frequently before and I thought I had stepped on all the mines there where but this one has got the best of me so far.
It's very very basic really. I use Assembly.LoadFrom("c:\\test\\mytestlibrary.dll") but Fusion cannot find the file (I get a FileNotFoundException).
I have examined the fusion logs as usual and it just doesn't make sense. Are there some circumstances that would somehow prevent Fusion from finding a file even when I provide the complete and absolute path to it? I suspected the dll in question needed some other assembly but looking at the fusion logs doesn't indicate this. Besides, the test library references nothing that's not also referenced by the host assembly.
Any suggestions?
Perhaps this blog entry by Suzzanne Cook will provide some clues?
For FileNotFoundException:
At the bottom of the log will be the paths that Fusion tried probing for this assembly. If this was a load by path (as in Assembly.LoadFrom()), there will be just one path, and your assembly will need to be there to be found. Otherwise, your assembly will need to be on one of the probing paths listed or in the GAC if it's to be found.
You may also get this exception if an unmanaged dependency or internal module of the assembly failed to load. Try running depends.exe on the file to verify that unmanaged dependencies can be loaded. Note that if you re using ASP.NET, the PATH environment variable it's using may differ from the one the command line uses. If all of them could be loaded, try ildasm.exe on the file, double-click on "MANIFEST" and look for ".file" entries. Each of those files will need to be in the same directory as the manifest-containing file.
-- http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57120.aspx
IIRC, the fusion log should also show the list of paths sought. Is your path included? Further, is the assembly already loaded as a project reference or otherwise previously in the same app domain?
I have 2 projects.
The first one just generates a DLL.
The second one needs the first DLL.
But when I call a method from the DLL, I have a FileNotFoundException, with this message :
BDD, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
I'm sure that the file exists.
Where I'm wrong ?
Agree with Kieren (+1). Maybe it is finding your DLL but it requires another dependent DLL that cannot be found. Or is there a signature issue (maybe you are looking for another DLL version, etc...)
To turn on fusion Log (you'll have to create a couple fo registry keys):
BTW, fusion is the DLL that contains the logic to load an assembly (probing for local path and subfolders if specified, looking at the GAC, ...). After running your executable, you'll find a log detailing the issues the CLR has found when loading referenced assemblies (ignore the NativeImage logs, inspect just the Default logs).
Short answer: The DLL needs to be in the same directory as the EXE.
Is this the case?
Could you give the full message - and:
Please bear in mind that the FileNotFoundException could be for a dependency of the referenced DLL, not just the referenced DLL itself.
You might want to turn on assembly-binding log (Fusion log) to see what's going on, if the DLL is indeed present.
Can I just use?:
Assembly.LoadFile
Not sure if this is the way to do this?
But when I try that approach, it throws a Could not load file or assembly "CustomControlLib" or one of its dependencies. The system cannot find the file specified.
Any ideas?
You will need to make sure that the dependencies are also loaded into the app domain. If they aren't located automatically, you can subscribe to AppDomain.AssemblyResolve in order to find and load assemblies manually if needs be.
For example:
private Assembly AssemblyEventHandler(object sender, ResolveEventArgs args)
{
return locatedAssembly;
}
Also, I would consider using Assembly.LoadFrom, particularly after reading this which has a strong assertion by nobugz and links to some good reading (all dated but ought to still be withstanding for the most part.)
If you use Assembly.LoadFrom() dependencies will be loaded from the directory where assembly is located.
Assembly.LoadFile() is ignoring all other DLLs and exe files in the same folder.
Yes, you can load a .Net exe the same way as you would load a Dll. The error you get is caused by dependencies of your exe. Make sure that the those dependencies can be found, i.e. are in your assembly search path.
Yes, you can use Assembly.LoadFile(). Check your path.