Using C#, I create a DLL at runtime and now I want to add it as a reference to my project at runtime.
I tried using the LoadFrom method, but it doesn't work.
How can I do this?
First you should load the dll
Assembly assembly = Assembly.LoadFrom("dllPath");
Then you may need to add the assembly to the app domain
AppDomain.CurrentDomain.Load(assembly.GetName());
After that you can load any type from this assembly
Type t = assembly.GetType("typeName");
Then using reflection you can execute methods on this type
Note that you may need to add the below in the configuration file.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="dlls folder"/>
</assemblyBinding>
</runtime>
LoadFile vs. LoadFrom
Be careful - these aren't the same
thing.
LoadFrom() goes through Fusion and can
be redirected to another assembly at a
different path but with that same
identity if one is already loaded in
the LoadFrom context. LoadFile()
doesn't bind through Fusion at all -
the loader just goes ahead and loads
exactly* what the caller requested. It
doesn't use either the Load or the
LoadFrom context. So, LoadFrom()
usually gives you what you asked for,
but not necessarily. LoadFile() is for
those who really, really want exactly
what is requested. (*However, starting
in v2, policy will be applied to both
LoadFrom() and LoadFile(), so
LoadFile() won't necessarily be
exactly what was requested. Also,
starting in v2, if an assembly with
its identity is in the GAC, the GAC
copy will be used instead. Use
ReflectionOnlyLoadFrom() to load
exactly what you want - but, note that
assemblies loaded that way can't be
executed.)
LoadFile() has a catch. Since it
doesn't use a binding context, its
dependencies aren't automatically
found in its directory. If they aren't
available in the Load context, you
would have to subscribe to the
AssemblyResolve event in order to bind
to them.
ref Suzanne Cook's .NET CLR Notes
Use Assembly.LoadFile method and then run code inside it using reflection.
Actually Assembly.Load is usually what you'd want, not LoadFrom and not LoadFile:
Which context is right for you? In
general, I strongly recommend that you
use the Load context whenever possible
http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57143.aspx
You cannot add dll to a project when project is already running. However, you can load the dll using Assembly.LoadFrom( filename). Normally such scenerio is used for SOA or plugin based projects. You can use interface to specify the type structure and load the dll and use it.
You could use the Assembly.LoadFrom method to dynamically load an assembly at runtime.
This is very simple in .NET: http://msdn.microsoft.com/en-us/library/1009fa28.aspx
Related
It's my impression that Assembly.LoadFrom uses the ApplicationBase and PrivateBinPath. It also my impression that Assembly.LoadFile does not.
Why would anyone want to use LoadFile? In other words, if my understanding is correct, why would anyone want to NOT use the ApplicationBase and PrivateBinPath?
I'm working with some existing code, which uses LoadFile, and I don't understand why it would do so. LoadFile apparently does not load dependencies from the same directory. The LoadFrom method does load dependencies (From the doc: The load-from context...allows dependencies on that path to be found and loaded because the path information is maintained by the context.) I'd like to convert it from using LoadFile, to use LoadFrom.
What is likely to break, if anything, if I replace LoadFile with LoadFrom?
Even if it iss benign, it may be that I cannot do the replacement, just based on project schedules. If I cannot replace LoadFile with LoadFrom, is there a way to convince assemblies loaded with LoadFile to load dependencies? Is there a packaging trick I can use (embedded assembly, ILMerge, an AssemblyResolve event, something like that) that can allow an assembly loaded with LoadFile to also load its dependencies?
Be careful - these aren't the same
thing.
LoadFrom() goes through Fusion and can
be redirected to another assembly at a
different path but with that same
identity if one is already loaded in
the LoadFrom context. LoadFile()
doesn't bind through Fusion at all -
the loader just goes ahead and loads
exactly* what the caller requested. It
doesn't use either the Load or the
LoadFrom context.
http://blogs.msdn.com/b/suzcook/archive/2003/09/19/loadfile-vs-loadfrom.aspx
In addition to Madhur Ahuja's answer, note that in most cases it is actually Assembly.Load that you'd want to use.
http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57143.aspx
OK, I have the following bit of code:
Assembly assembly = Assembly.LoadFile("W:\\AssemblyFoo.dll");
foreach (Type type in assembly.GetExportedTypes())
{
foreach (object attribute in type.GetCustomAttributes(false)) //Exceptio on that line
{
string attributeString = attribute.ToString();
}
}
The code throws the following exception: Could not load file or assembly 'AssemblyBar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
The problem is that one of the attribute is in AssemblyBar, which is referenced by AssemblyFoo, but not directly by the current's project (ProjectBaz) assembly. I'd rather avoid referencing AssemblyBar directly in ProjectBaz, since AssemblyFoo is selected by the user. What's the correct way to go about this ? I'm pretty sure I'm missing something easy.
I know it's possible since Reflector does it.
Mono's Cecil
You may circumvent the problem by not loading the assemblies through the built-in reflection
facilities, using a tool like Mono.Cecil instead. I've had good experiences in applying it for analysis tasks.
From the Cecil site:
with Cecil, you can load existing
managed assemblies, browse all the
contained types, modify them on the
fly and save back to the disk the
modified assembly.
CCI Metadata
As an alternative to Cecil, you might consider CCI Metadata by Microsoft Research. I have not used that tool, so I can not comment on how it stacks up to Cecil.
Hope this helps.
You could include AssemblyBar in you bin directory so that the clr can load it.
MemberInfo.GetCustomAttributesData() was introduced in .NET 4 so that you could examine custom attributes without having to instantiate them.
UPDATE: Taking closer look at MemberInfo.GetCustomAttributesData(), although it doesn't instantiate the attributes, it still need to load the assembly. My apologies.
Another possible route to investigate would be Mono Cecil. You can load the Mono.Cecil assembly and use it with the .NET Framework, not just Mono. It is much more powerful than System.Reflection and Reflection.Emit. According to its homepage:
Cecil does not need to load the assembly or have compatible assemblies to introspect the images.
This sounds exactly like what you're trying to do.
I want to add some behavior to a certain class at runtime. I know how to subclass at runtime using Reflection.Emit but that's not enough. Depending on some external configuration I need to inject opcodes in a method on a type T so all classes that inherit from it automatically gain this behavior. (I can't use the .NET Profiling API).
Can something like this be done with Mono.Cecil?
If it isn't possible to modify code on a loaded assembly, it is fine If I can make the modifications before the assembly is loaded and then load the modified assembly in memory, but I don't know how I can control assembly loading.
Nope, Cecil can not modify a loaded assembly. You have to instrument assemblies before they are actually loaded.
You don't have much control over how assemblies are resolved. You can hook into AppDomain.AssemblyResolve if you hide the assemblies in a private folder of yours, and instrument then before loading them.
As JB Says above-
You can create a Resolve Event handler - which would be like PSeudoHooking.
And before the assembly is loaded, you make your changes, and then once the changes are done, the Resolve Assembly then continues on to load the changed assembly.
I use this method for resolving Embedded Dll's from Memory Streams.
If you create a class library that uses things from other assemblies, is it possible to embed those other assemblies inside the class library as some kind of resource?
I.e. instead of having MyAssembly.dll, SomeAssembly1.dll and SomeAssembly2.dll sitting on the file system, those other two files get bundled in to MyAssembly.dll and are usable in its code.
I'm also a little confused about why .NET assemblies are .dll files. Didn't this format exist before .NET? Are all .NET assemblies DLLs, but not all DLLs are .NET assemblies? Why do they use the same file format and/or file extension?
ILMerge does merge assemblies, which is nice, but sometimes not quite what you want. For example, when the assembly in question is a strongly-named assembly, and you don't have the key for it, then you cannot do ILMerge without breaking that signature. Which means you have to deploy multiple assemblies.
As an alternative to ilmerge, you can embed one or more assemblies as resources into your exe or DLL. Then, at runtime, when the assemblies are being loaded, you can extract the embedded assembly programmatically, and load and run it. It sounds tricky but there's just a little bit of boilerplate code.
To do it, embed an assembly, just as you would embed any other resource (image, translation file, data, etc). Then, set up an AssemblyResolver that gets called at runtime. It should be set up in the static constructor of the startup class. The code is very simple.
static NameOfStartupClassHere()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver);
}
static System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args)
{
Assembly a1 = Assembly.GetExecutingAssembly();
Stream s = a1.GetManifestResourceStream(args.Name);
byte[] block = new byte[s.Length];
s.Read(block, 0, block.Length);
Assembly a2 = Assembly.Load(block);
return a2;
}
The Name property on the ResolveEventArgs parameter is the name of the assembly to be resolved. This name refers to the resource, not to the filename. If you embed the file named "MyAssembly.dll", and call the embedded resource "Foo", then the name you want here is "Foo". But that would be confusing, so I suggest using the filename of the assembly for the name of the resource. If you have embedded and named your assembly properly, you can just call GetManifestResourceStream() with the assembly name and load the assembly that way. Very simple.
This works with multiple assemblies, just as nicely as with a single embedded assembly.
In a real app you're gonna want better error handling in that routine - like what if there is no stream by the given name? What happens if the Read fails? etc. But that's left for you to do.
In the rest of the application code, you use types from the assembly as normal.
When you build the app, you need to add a reference to the assembly in question, as you would normally. If you use the command-line tools, use the /r option in csc.exe; if you use Visual Studio, you'll need to "Add Reference..." in the popup menu on the project.
At runtime, assembly version-checking and verification works as usual.
The only difference is in distribution. When you deploy or distribute your app, you need not distribute the DLL for the embedded (and referenced) assembly. Just deploy the main assembly; there's no need to distribute the other assemblies because they're embedded into the main DLL or EXE.
Take a look at ILMerge for merging assemblies.
I'm also a little confused about why .NET assemblies are .dll files. Didn't this format exist before .NET?
Yes.
Are all .NET assemblies DLLs,
Either DLLs or EXE normally - but can also be netmodule.
but not all DLLs are .NET assemblies?
Correct.
Why do they use the same file format and/or file extension?
Why should it be any different - it serves the same purpose!
You can embed an assembly (or any file, actually) as a resource (and then use the ResourceManager class to access them), but if you just want to combine assemblies, you're better off using a tool like ILMerge.
EXE and DLL files are Windows portable executables, which are generic enough to accomodate future types of code, including any .NET code (they can also run in DOS but only display a message saying that they're not supposed to run in DOS). They include instructions to fire up the .NET runtime if it isn't already running. It's also possible for a single assembly to span across multiple files, though this is hardly ever the case.
Note ILMerge doesn't work with embedded resources like XAML, so WPF apps etc will need to use Cheeso's method.
There's also the mkbundle utility offered by the Mono project
Why do they use the same file format and/or file extension?
Why should it be any different - it serves the same purpose!
My 2¢ bit of clarification here: DLL is Dynamic Link Library. Both the old style .dll (C-code) and .net style .dll are by definition "dynamic link" libraries. So .dll is a proper description for both.
With respect to Cheeso's answer of embedding the assemblies as resources and loading them dynamically using the Load(byte[]) overload using an AssemblyResolve event handler, you need to modify the resolver to check the AppDomain for an existing instance of the Assembly to load and return the existing assembly instance if it's already loaded.
Assemblies loaded using that overload do not have a context, which can cause the framework to try and reload the assembly multiple times. Without returning an already loaded instance, you can end up with multiple instances of the same assembly code and types that should be equal but won't be, because the framework considers them to be from two different assemblies.
At least one way that multiple AssemblyResolve events will be made for the same assembly loaded into the "No context" is when you have references to types it exposes from multiple assemblies loaded into your AppDomain, as code executes that needs those types resolved.
https://msdn.microsoft.com/en-us/library/dd153782%28v=vs.110%29.aspx
A couple of salient points from the link:
"Other assemblies cannot bind to assemblies that are loaded without context, unless you handle the AppDomain.AssemblyResolve event"
"Loading multiple assemblies with the same identity without context can cause type identity problems similar to those caused by loading assemblies with the same identity into multiple contexts. See Avoid Loading an Assembly into Multiple Contexts."
I would suggest you to try Costura.Fody. Just don't forget to Install-Package Fody before Costura.Fody (in order to get the newest Fody!)
I try to add an addons system to my Windows.Net application using Reflection; but it fails when there is addon with dependencie.
Addon class have to implement an interface 'IAddon' and to have an empty constructor.
Main program load the addon using Reflection:
Assembly assembly = Assembly.LoadFile(#"C:\Temp\TestAddon\Addon.dll");
Type t = assembly.GetType("Test.MyAddon");
ConstructorInfo ctor = t.GetConstructor(new Type[] { });
IAddon addon= (IAddon) ctor.Invoke(new object[] { });
addon.StartAddon();
It works great when addon do not use dependencie.
But if my addon reference and use an another DLL (C:\Temp\TestAddon\MyTools.dll) that is saved near the addon in disk, it fails:
System.IO.FileNotFoundException: Could not load file or assembly 'MyTools.dll' or one of its dependencies.
I do not wants to copy the addons DLL near my executable, how can i do to tell .Net runtime to search in "C:\Temp\TestAddon\" for any dependency?
Note that adding
Assembly assembly = Assembly.LoadFile(#"C:\Temp\TestAddon\MyTools.dll");
do not change anything.
If MyTools.dll is located in the same directory as Addon.dll, all you need to do is call Assembly.LoadFrom instead of Assembly.LoadFile to make your code work. Otherwise, handling the AppDomain.AssemblyResolve event is the way to go.
Have you looked into using an Inversion Of Control container? I use Castle Windsor with an external Boo file that lets me easily extend the applcation without having to recompile or worry about supplying dependencies
You can use reflection to access the private Assembly._GetReferencedAssemblies().
Although, the method could change in a future version of the .NET framework, it doesn't seem likely—ASP.NET heavily depends on it, though it's possible they could move it from mscorlib to System.Web which is the only assembly that I know of from where the method is referred to.
Assembly.LoadFrom works well until I try to use a webService in my addon, I had had a "Unable to cast object of type 'X' to type 'X'" exception.
It's ugly, but i will use Assembly.LoadFile with the AppDomain.AssemblyResolve.
Thanks guys.
Couple of options:
You can attach to AppDomain.AssemblyResolve to help the CLR resolve the assembly.
You could look into isolating add-ins into their own AppDomain (see System.AddIn namespace and this website).