Using AppDomain in C# to dynamically load and unload dll - c#

In one of my application, which is related to system diagnostics, the related DLL is to be loaded and unloaded dynamically in C#. After some search I found that a separate DLL cannot be loaded dynamically its the complete AppDomain. So I have to create an AppDomain and use that DLL to be loaded unloaded dynamically. But I could not find anywhere how can I use that in code. I can not show the app code since it is against company rules.
Can somebody tell me some application code to use it. I want to load and unload the dll dynamically using appdomain and call a specific method in that dll, the dll does not have any entry point.
Thanks for answers.
Ashutosh

How to: Load Assemblies into an Application Domain
public static void Main()
{
// Use the file name to load the assembly into the current
// application domain.
Assembly a = Assembly.Load("example");
// Get the type to use.
Type myType = a.GetType("Example");
// Get the method to call.
MethodInfo myMethod = myType.GetMethod("MethodA");
// Create an instance.
object obj = Activator.CreateInstance(myType);
// Execute the method.
myMethod.Invoke(obj, null);
}
As for how to unload it, you have to unload the AppDomain itself, see this
AppDomain Temporary = AppDomain.CreateDomain("Temporary");
try
{
Gateway Proxy =
(Gateway) Temporary.CreateInstanceAndUnwrap("Shim", "Shim.Gateway");
Match M = Proxy.LoadAndMatch("Plugin.dll",
"Though the tough cough and hiccough, plough them through");
}
finally
{
AppDomain.Unload(Temporary);
}

It's difficult to understand your question, but I will try to make some suggestions.
There is no reason you cannot dynamically Load a dll directly into your application w/o a separate App Domain, the trick is that you cannot unload it. This is only important if you may load multiple versions of the same dll (i.e. you want the ability to update this diagnostic component to a new version without halting the execution of your application). If that is what you are trying to do, then I suggest this CodeProject article.

Actually you can dynamically load assemblies into your app domain and run code from it, the issue is that you cannot then unload the assembly. You can however load additional app domains (and assemblies into them) and unload the app domain when you are done.
As its name suggests though, you then have a new application domain, and you can't just simply call its code and use its types you need to marshal your calls and data across the domain boundaries. If you search you will find lots of examples on how to do this.
Something to consider though, is that this is a common pattern, and there are ready made solutions for it, the framework itself has a whole addin namespace that is dedicated to this type of plug-in behavior, it might be worth your while in having a close look at that first. There is an article here that shows how to use it.

Thanks guys, here is link where i found answer to my quetion:
The MSDN forum description for load and unload of assemblies dynamically
The other dll can be dynamically loaded and unloaded using another class which does load assembly and and call methods in that assembly...
AppDomain.CreateInstanceAndUnwrap generally wants input as assemblies from current project or generally current namespace. to solve that i need Assembly.LoadFrom(); to be used in some other class and create AppDomain and create instance of this class using AppDomain object as given in link.
Thanks for ur replies guys.

Related

Plugin registration without instantiating the plugin class

I need to design a simple plugin framework for our application (.NET, WinForms 3.5).
The extension points will be several application events/scenarios that the user could "hook" into using a plugin, to perform a certain operation.
The way i would like this to work is:
Have a Plugins folder where users will place plugin DLLs (assemblies containing types derived from a specific base class/marked somehow).
Have my application plugin system locate these files and register them for later usage.
Invoke the right plugin at the right time (for example: OnException, OnLog, etc).
If i will create the plugin object (new it up) at registration, the DLL would be loaded into the process memory.
I am looking for an easy way to do the registration, and only "lazily" load the plugin assembly, when needed (IF needed at all).
You have a couple options for this - If you are able, you could require that each plugin provide a manifest or some other file that describes itself, and then you could examine all the manifests and load the appropriate plugin when necessary. This avoids examining the assembly, but it does require consistency between the manifest and the assembly, which can be tricky.
Otherwise, as you've indicated, examining the plugin assembly will load it into memory. The only way I've discovered to avoid this is to load them into a separate AppDomain, examine them and capture necessary information, then unload that AppDomain. There is an example of doing this for PRISM somewhere (I can try to track it down), but I'm not sure what framework you're using (MEF, MAF, PRISM, IoC, etc.).
An alternative to loading each candidate assembly in a new AppDomain, reflecting on it's types and finally unloading the AppDomain, you could try Mono.Cecil. You then will have to do something like this:
AssemblyDefinition ad = AssemblyDefinition.ReadAssembly(assemblyPath);
foreach (TypeDefinition td in ad.MainModule.GetTypes())
{
if (td.BaseType != null && td.BaseType.FullName == "MyNamespace.MyAddInBase")
{
return true;
}
}
Then you can load the right assemblies using Assembly.LoadForm and finally create instances of the add-ins using the Activator.CreateInstance overload that suits your needs.

Marshalling Assembly from another AppDomain

Is it possible to hold a reference to an Assembly from another appdomain without having that assembly loaded into the current appdomain?
I'm working on fixing a memory leak in a Windows Service that dynamically generates Assemblies and runs the dynamically generated code. The problem is the generated Assemblies are loaded into the Current app domain and can never be unloaded.
There is a method in one of the Windows Service libraries that has the follow signature:
public Assembly CreateMethod(ObservableCollection<Field> sourceFields, Field destinationField)
This method creates the code for the assembly and loads it with the CSScript library LoadMethod function:
result = CSScript.LoadMethod(scriptFunction.ToString());
Later this Assembly reference from CreateMethod is used to run a function inside the generated assembly.
public object Run(Field destinationField, ObservableCollection<LinkField> sourceLinkFields, DataRow mainRow, Assembly script) {
...
var method = script.GetStaticMethodWithArgs("*.a" + Id.ToString().Replace("-", String.Empty), argumentTypes.ToArray());
return method(arguments.ToArray());
}
I'm wondering if it is possible to load the dynamically generated assembly into another app domain and run them through some type of proxy without having it loaded into the current app domain.
Edit:
I want to know if I can use an Assembly class reference in one AppDomain when the assembly is loaded in another AppDomain. Looking at the MSDN documentation they show how to use MarshalByRefObject. Basically I am trying to avoid changing the signature to my CreateMethod function, however I may need to change it to return MarshalByRefObject if this is not possible.
Update:
I ended up putting the call to CSScript.LoadMethod in the other app domain where I keep a Dictionary I then made CreateMethod return a Guid instead of an Assembly and then I pass this Guid around until the Run call. The Run call now takes a Guid as an argument instead of an Assembly. Inside the Run call I pass the Guid to the other app domain, run the method, and return the result object through a class that inherits MarshalByRefObject.
If you don't want the dynamic assembly in your main AppDomain, you have to move CreateMethod to another AppDomain, because as soon as you have an instance of Assembly, it's been loaded. In other words, no it is not possible to hold a reference to an assembly in another application domain, only to call into that assembly across application domains.
Without changing the signature and a bunch of your code, it seems like you need to move the minimum amount: 1) assembly creation and 2) Run. Then have the implementation of Run marshall the results.
As far as CreateMethod I think you want a method in the other assembly to "wrap" CreateMethod and return some sort of token that can be passed to Run. It's almost like changing the signature in a way...
This is one of the major features of an AppDomain! Just go look at the documentation

C# Controlling dll access

I have a program that utilises a plugin architecture. When the inital form loads, it scans the current directory, queries each dll and obtain some basic data which is displayed to the user.
Whilst using the program, the software will often need to ask the dll's to perform some work.
My question is, when the program initially checks the dll files, should I keep a reference to each dll object for future use, or should I query the dll files each time and create the object as and when needed?
if it's the first one, what is the best way to keep a list of an undetermined number of objects that derive from a common interface and then know which one to refer back to when needed?
Thanks.
Using the first one you could just create a
List<IYourCommonInterface> pluginDlls
and then just
pluginDlls.Add(dllReference);
Edit
Alternate method using a Dictionary, note that this will require you having some kind of ID for the dictionary that you can make use of to id the dlls.
Dictionary<SomeIDField, IYourCommonInterface> pluginDlls
pluginDlls.Add(dllRefrence);
Most apps do the check on load.
I wouldn't store the list of interfaces. If you do store them then you run into the possibility that the assemblies either disappear or are updated in some way. At which point you need to "refresh" them anyway.
Once you've loaded the assembly and gotten an instance of System.Reflection.Assembly for reflection (using Assembly.Load(), Assembly.LoadFrom(), Assembly.LoadFile(), etc.), the assembly is loaded. To quote MSDN on the subject:
...it is...possible to load specific assemblies into the current application domain
at runtime...There is no way to unload an individual assembly without unloading
all of the application domains that contain it. Even if the assembly goes out of
scope, the actual assembly file will remain loaded until all application domains
that contain it are unloaded. [emphasis mine]
So if you want to unload the DLLs until such time as you actually need them, you're going to have to create a new app domain and then unload that. Its easier to just load them and have done with it. You can keep the assemply reference around if you like, but if you call Assembly.Load() again, it won't actually load the assembly: it'll just get a reference to the previously loaded assembly.
If you've gone through the trouble of finding and loading the DLLs, normally you'll want to keep them around. This would depend mostly on how many resources the DLLs use and how your app is using the DLLs.
I'm assuming you're using LoadAssembly here. You can just store references to the assemblies you've loaded using some kind of map. Or even a list that you iterate through.
Perhaps if you give some more details we can help you better.

Dynamically Generate Modules in same Assembly Space

Consider I have a program running, which should do the following-
Should read some code from a text file and should execute it in its own Assembly space so that the new code being executed can access all components of the code already running.
How is that possible?? Help please.
By assembly space, do you mean AppDomain?
You might want to look at IronPython. As a scripting language it is better suited for being dynamically added to the program at runtime.
Otherwise:
You have access to the C# (and VB.NET) compiler via the Microsoft.CSharp.CSharpCodeProvider sitting in System.dll.
You can use it to compile that text file into a separate dll (possibly in-memory). Make sure that you add your currently executing assembly as a reference while compiling. Then you can either
load the assembly into the currently executing AppDomain. This way, it has access to all the objects in your application. You, however, cannot unload the code again. You'll have to unload the whole AppDomain (i.e. your application)
load the assembly into a separate AppDomain. You'll have to explicitly provide access to some of your objects via Remoting (or other in process communication methods), but you can unload/replace the code in case the text file changes.
Either way, you'll have to use reflection to call your dynamically loaded code.
Not sure how the magic works, but I'd look at MyGeneration, which is open source and acheives what you want to do. It can read a file of C#, VB.Net, and JScript and then build/compile those scripts and gives them access to it's own set of classes and assemblies.

How Do I Load an Assembly and All of its Dependencies at Runtime in C# for Reflection?

I'm writing a utility for myself, partly as an exercise in learning C# Reflection and partly because I actually want the resulting tool for my own use.
What I'm after is basically pointing the application at an assembly and choosing a given class from which to select properties that should be included in an exported HTML form as fields. That form will be then used in my ASP.NET MVC app as the beginning of a View.
As I'm using Subsonic objects for the applications where I want to use, this should be reasonable and I figured that, by wanting to include things like differing output HTML depending on data type, Reflection was the way to get this done.
What I'm looking for, however, seems to be elusive. I'm trying to take the DLL/EXE that's chosen through the OpenFileDialog as the starting point and load it:
String FilePath = Path.GetDirectoryName(FileName);
System.Reflection.Assembly o = System.Reflection.Assembly.LoadFile(FileName);
That works fine, but because Subsonic-generated objects actually are full of object types that are defined in Subsonic.dll, etc., those dependent objects aren't loaded. Enter:
AssemblyName[] ReferencedAssemblies = o.GetReferencedAssemblies();
That, too, contains exactly what I would expect it to. However, what I'm trying to figure out is how to load those assemblies so that my digging into my objects will work properly. I understand that if those assemblies were in the GAC or in the directory of the running executable, I could just load them by their name, but that isn't likely to be the case for this use case and it's my primary use case.
So, what it boils down to is how do I load a given assembly and all of its arbitrary assemblies starting with a filename and resulting in a completely Reflection-browsable tree of types, properties, methods, etc.
I know that tools like Reflector do this, I just can't find the syntax for getting at it.
Couple of options here:
Attach to AppDomain.AssemblyResolve and do another LoadFile based on the requested assembly.
Spin up another AppDomain with the directory as its base and load the assemblies in that AppDomain.
I'd highly recommend pursuing option 2, since that will likely be cleaner and allow you to unload all those assemblies after. Also, consider loading assemblies in the reflection-only context if you only need to reflect over them (see Assembly.ReflectionOnlyLoad).
I worked out Kent Boogaart's second option.
Essentially I had to:
1.) Implement the ResolveEventHandler in a separate class, inheriting from MarshalByRefObject and adding the Serializable attribute.
2.) Add the current ApplicationBase, essentially where the event handler's dll is, to the AppDomain PrivateBinPath.
You can find the code on github.

Categories

Resources