Ok, heres the rundown...
I have a service that is running and it references a dll that is changed a lot. This service is hopefully going to have multiple clients hitting it at once so it would be inefficient to shut it down and recomplile/reload with a new reference. I was wondering if there was anyway the program could pretty much auto-detect a dll with a later version and just drop the old one and load the new one without having to be shut down.
This can be difficult to achieve in a .Net application. Once a DLL is loaded into a particular AppDomain there is no way to unload the DLL from the AppDomain. The only way to get the DLL out of the process is to unload the AppDomain itself.
You could achieve what you're trying to accomplish by having the DLL loaded into a secondary AppDomain, and restarting that AppDomain with the new DLL when you detect a change. This also involves using some advanced shadow copy features though to allow the DLL to be deleted while being used by the process.
The only way to do this is move the code that uses the assembly to its own AppDomain. You can shutdown the AppDomain and restart it with the new assembly.
See this question: How to reload an assembly in C# for a .NET Application Domain?
The Managed Extensibility Framework will allow you to do this.
Related
Is there a good way in C# to check if all referenced DLLs are installed on the target machine?
What I want to achieve is that my software doesn't start if one of the referenced DLLs are missing on the target machine. Based on that I can be sure that my features won't break during runtime because a DLL can't be found.
My idea: Create a separate AppDomain during startup, and load ALL referenced DLLs to it. If it fails I'd shut down my software. If loading succeeds I'd unload the separate AppDomain and proceed to start the software. Is it a good idea to perform the check in such a manner, or are there some known problems/pitfalls around it.
I'm aware that I posted no corresponding piece of code, I only want to gather feedback if my idea is a good one or not.
Thx
I'm creating some tool what performs several operations like NUnit.
Inside this tool I open .dll assembly and invoke methods form it to run some test.
Everything is going OK till the time I need to reload .dll withour program restart. The idea is that when tool is run we copy required assembly to some temporary folder and invoke from there. If I need to reload I copy another one to another temporary folder and try to load newly copied from another folder and load to previous assembly object
ExecutingAssembly = Assembly.LoadFrom(AssemblyFullPath);
But my problem is that after I change AssemblyFullPath to new one and call Assembly.LoadFrom it returns just old assembly what was loaded first time but not the second one!
Maybe the problem is that we cannot load several assemblies with different versions? What is the solution?
The CLR does support loading multiple versions of strongly named assemblies into the same AppDomain. This only works though if your assemblies are strongly named and each one has a different version than the other.
I'm guessing it's more likely that you are dealing with unsigned assemblies. If that is the case then what you're asking for isn't really possible. Once a given assembly is loaded into an AppDomain it will remain there until the AppDomain is unloaded. To get this to work you will have to abstract out all of the work around the loaded assemblies into a separate AppDomain and use a new AppDomain for every assembly
To expand on JaredPar's answer, you will need to create a new AppDomain and use Remoting to communicate between the two.
Check out http://msdn.microsoft.com/en-us/library/kwdt6w2k(v=vs.85).aspx to help get you started.
Try like this:
string dllFile = "C:\\sample.dll";
Assembly asmLoader = Assembly.LoadFile(dllFile);
Type[] types = asmLoader.GetTypes();
Since all resources from the assembly cannot be reloaded/replaced it's assembly resources while application is still running. It will only be replaced/removed when application is unloaded or the that Assembly that holds it.
Use LoadFile() method. Hope it helps.
I have a COM+ Application composed of several serviced components.
One of them instantiates on demand a type from a dll through Activator.CreateInstance(pluginType, args);. The type is not a serviced component itself, it contains just the implementation of certain interface that the component knows about.
I don't have problems with the instantiation itself, the problem is that the dll is getting locked by the dllhost.exe, and I would like, if possible, to be able to replace it without shutting down the COM+ Application.
Is it possible somehow to unlock the dll without shutting down the COM+ App?
Or from another point of view, is there a way I could programmatically unload the dll to unlock it?
NOTE: The dll is located in the COM+ application root directory with rest of the dlls.
Loaded modules are referenced counted in windows. In windows we have loadLibrary and freelibrary. If freelibrary is called and the reference count is zero then the dll will be unloaded and free to replace, delete, etc.
In .NET though once an assembly is loaded into an appDomain it is there until the appdomain dies (unless reflection emit collectable assembly). If you were to spawn another appdomain and do the create instance here when the new appdomain dies the assembly will be unloaded.
Asp.net does something called shadow caching. Asp.net you can replace the dlls at anytime without having to kill the worker process. They do this by not loading the dlls in the bin folder but instead they copy them to a seperate location and load them from there in a seperate appdomain. They watch the bin folder, when a change happens they kill the appdomain, copy the dlls to the temp folder, and create a new appdomain.
Shadow Copying Assemblies
http://msdn.microsoft.com/en-us/library/ms404279.aspx
This is not a specific problem for COM+, it is universal on Windows and fundamental to the way it works. Loading code from an executable file (exe or dll) is done by Windows creating a memory-mapped file for the executable file. Code is only read from the file when a page fault requires actually reading the file and mapping the code into RAM. This will happen repeatedly when other processes compete for RAM and the code gets unmapped.
The MMF puts a lock on the file. Required so that the file cannot be modified while it has code mapped into RAM.
There's no workaround for this, the process that has the DLL loaded must terminate or must cooperate and unload the DLL before the lock is released. At best you can rename the file while it is in use, that doesn't otherwise affect the process.
Is there such a thing as delay loading a dll in C#?
I know this is possible to do in C++, but what about managed code?
.NET does that automatically, everything is loaded on demand by default.
This article explains in detail how it works in .NET. Summary of key points:
There are a number of different ways that assemblies are loaded in
.NET. When you create a typical project, assemblies usually come from:
The Assembly reference list of the top level 'executable' project
The Assembly references of referenced projects
Dynamically loaded assemblies, using runtime loading via AppDomain or Reflection loading
and
.NET automatically loads mscorlib (most of the System namespace) as part of the .NET runtime hosting process that hoists up
the .NET runtime in EXE apps, or some other kind of runtime hosting
environment (runtime hosting in servers like IIS, SQL Server or COM
Interop).
and
Dependent Assembly References are not pre-loaded when an application starts (by default)
Dependent Assemblies that are not referenced by executing code are never loaded
Dependent Assemblies are just in time loaded when first referenced in code
Once Assemblies are loaded they can never be unloaded, unless the AppDomain that hosts them is unloaded.
Yes it is. You don't include the DLL as a reference in your project and where you want to load/use it, you call the Assembly.LoadFile method.
This blog post does a pretty good job with code to describe how to do it.
I have 2 assemblies. Assembly2 is referenced by Assembly1.
Why is Assembly2 locked?
I thought the whole assembly is loaded into the RAM by the JIT-Compiler, isn't it?
How does the machinism work when a referenced assembly is called?
(yes, the question could have been better, still...)
Referenced assemblies are loaded into the process and are thus locked. You can get around this with shadow copying, or just make sure you close every process that uses your assemblies before you attempt to modify them.
I ran into a situation when writing a .NET componenet to be consumed in a VB6 app where I couldn't deploy my recompiled .NET assembly while the VB6 editor was open. This really frustrated me because I wanted to be able to just make a quick change and then have the change show up in my VB6 editor. I was getting an error message that the assembly was locked by another process or thread.
I later realized that this made a lot of sense. If the referencing application (in my case, the VB6 IDE) is trusting that library to be the same each time it goes to consume it, it's going to run into serious problems if the dll changes while the application is in memory.
In my case, closing the VB6 IDE, updating the dll, and reopening the VB6 IDE worked just fine. It was a little bit of a hindrance in my workflow, but once I realized why it was happening, I got over it.