How to update dll while using it in Visual Studio - c#

I want to replace dll "a" to their new version while the application is running, but when I trying to make it, I getting error: IOException that this file already using by process.
How can I replace it without getting this error?

Even if you were able to do what you're describing, and you're not, but even if you were, the code that's already executed, along with a large portion of the code physically around it has already been loaded in memory by the pre-loader and JIT. A large part of that was probably also already JITed. So you replacing the file would only affect new page faults, leading to internal corruption when they resolve against your new library.
Instead .Net provides AppDomain instances to let you load and unload libraries into for a moderate performance cost when using them, allowing you to unload your libraries when you want to do your update magic.
However I cannot stress enough how unviable your solution is. The standard update process is, and always has been:
download your new files in a separate folder
start a second, smaller, preferably C++ application (less prerequisites) that:
waits for the main application to close (you can use a named mutex)
copies the files from the temp folder over to the main folder
handles any errors, and deletes the temp folder if everything went alright
starts the main application again
as soon as the second application is started, exit out of the main application

One of possible solutions.
Note: in this solution constructor must be parameterless. Logic with input parameters must be separated to Initialize() method.
Separate all models/interfaces/enums etc. from
project "a" to another project (let's call it "Models").
Make reference from Models to both project a and your executable project.
Remove reference from a to your executable project (but make sure that your a.dll will be placed in same folder as executable).
In your executable project add next Helper:
using System;
using System.Linq;
using System.Reflection;
...
public static class DynamicLoader
{
public const string MyLibName = "a.dll";
public static T Create<T>(this T type)
{
Assembly asm = Assembly.LoadFrom(MyLibName);
Type assemblyType;
assemblyType = typeof(T).IsInterface ? asm.GetTypes().First(p => typeof(T).IsAssignableFrom(p)) : typeof(T);
return (T)asm.CreateInstance(assemblyType.FullName);
}
}
...
//Usage example:
Models.SomeType instance = typeof(Models.SomeType).Create();
instance.Initialize(15);
With this you can replace your "a.dll" and next call of Create() returns instance from new file.

Related

Is it possible to create a DLL which contains another DLL?

I am working on a project. The task is to create a DLL Project. In that project, I am having an existing DLL with set of methods. With the use of existing DLL I can call some methods and create some methods in the new DLL.
Is that Possible in C#? What are the possibilities and methods to create such a project?
If you want to hide that DLL in the contents of your own DLL, you can simply put it into resources. From the standpoint of resources, a DLL is just a file like any other and you can simply add it to program resources and simply drop the file where you need it.
However this will prohibit you from using implicit linking and you will have to link the DLL explicitly. MSDN already offers a quite reasonable tutorial already and here.
using System;
using System.Reflection;
public class Asmload0
{
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);
}
}
If you want to create your own DLL that just uses the old one you may just Add Reference. Then you can set up "Use Copy Local", but you will have to distribute two files:
And if you want to make "static link" simply by compiler/linker (build in to visual studio) you need to use a statically linked library (LIB) and not a dynamically linkws library (DLL)...
Or you can try reading "How to link a .DLL statically?" which seems to provide some guidance (proprietary software) on how to do this.

How can I get a portion of my C# app to load dynamically without app restart?

My C# application server.exe is critical to my business operations and ideally needs to run without interruption 24/7. The code is rock solid but one thing that's out of my control is the poor quality of inbound data feeds that are generated by third parties. I'll occasionally receive data feeds that contain anomalies in which case I must:
update the feed processing code within server.exe to accommodate the anomaly
recompile
restart server.exe using the new code and allow the syntactically flawed feed to be processed
The whole process usually takes less than a couple of minutes but the restart of server.exe causes the reset of certain non-critical state information and worse, causes a disruption of external processes that depend upon server.exe.
My goal: Isolate the feed processing code into a separate DLL whose contents can be updated without restarting server.exe. How do I do this?
Allow me to explain what I've done so far prior to writing this forum post:
The feed processor interface has been moved to a new assembly called common.dll. The interface looks something like this:
public interface IFeedProcessor{
bool ProcessFeed(String filePath); //returns false on failure, true on success
}
Server.exe now references common.dll.
The feed processors themselves have been moved to a new assembly called feedProcessors.dll. The implementations look something like this:
internal class FeedProcessor1:IFeedProcessor{
public FeedProcessor1(){}
bool ProcessFeed(String filePath){/*implementation*/return true;}
}
internal class FeedProcessor2:IFeedProcessor{
public FeedProcessor2(){}
public bool ProcessFeed(String filePath){/*implementation*/return true;}
}
[... and so on...]
feedProcessors.dll also contains a class named FeedProcessorUtils that's used to create a specific feed processor based on some configuration inputs. It looks something like this:
public class FeedProcessorUtils{
public static void CreateFeedProcessor(int feedType /*and other configuration params*/){
switch(feedType){
case 1:return new FeedProcessor1();
case 2:return new FeedProcessor2();
default: throw new ApplicationException("Unhandled feedType: "+feedType);
}
}
}
Everything works just as before but of course it doesn't solve my dynamic loading problem; If I updated feedProcessors.dll with new code and copy it to the production server, I'm unable to do so because the file is in use. No surprise there. So what's the solution?
Ideally I want to be able to copy an updated feedProcessors.dll to the production server without a file-in-use error and without restarting server.exe. Then, the next time server.exe makes a call to FeedProcessorUtils.CreateFeedProcessor(), it'll be executing from my revised DLL instead of the old one.
Where do I start?
You want to use shadow copy assemblies for the dynamically loaded DLL
http://msdn.microsoft.com/en-us/library/ms404279(v=vs.110).aspx
Sounds like a classic place to use MEF: http://msdn.microsoft.com/en-us/library/dd460648(v=vs.110).aspx
I suggest you look into it and ask questions as you proceed.
In addition to the shadow copy option, you should create an AppDomain and check when your dll is changed to restart the domain and reload the dll, you can check this with a FileSystemWatcher.
Take care of not directly referencing your classes between AppDomains, or your old assembly will never be unloaded.

Loading multiple versions of DLLs

I have a C# application which interfaces with some hardware (USB device) as follows:
C# application -> intermediate DLL -> hardware DLL -> hardware. The intermediate DLL and hardware DLL are supplied with the USB device so I have no control over these.
The intermediate DLL is the only which which I need to include in the VS project as this is what I call. The hardware DLL is then in the same directory so must be found automatically.
A new version of hardware device is now released with a different hardware DLL. The old DLL is not compatible with the new hardware and the new DLL is not compatible with the old hardware.
How can I make my application work with both pieces of hardware? I guess that I need to load and unload each DLL as required?
Here's what I do for a similar problem. I have a chunk of code that I want to work with, but I have to load the dll at runtime. So I refer to it in my project, but I don't put it in the same directory as the rest of my assemblies. Instead, in the consuming code, I have some code that looks like this:
// constructor called from a static constructor elsewhere
MyDllLoader(string hardwareFolder) {
_hardwareFolder = hardwareFolder;
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
SeeIfAlreadyLoaded();
}
private void SeeIfAlreadyLoaded() {
// if the assembly is still in the current app domain then the AssemblyResolve event will
// never fire.
// Since we need to know where the assembly is, we have to look for it
// here.
Assembly[] assems = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly am in assems)
{
// if it matches, just mark the local _loaded as true and get as much
// other information as you need
}
}
System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {
string name = args.Name;
if (name.StartsWith("Intermediate.dll,"))
{
string candidatePath = Path.Combine(_hardwareFolder, "Intermediate.dll");
try {
Assembly assem = Assembly.LoadFrom(candidatePath);
if (assem != null) {
_location = candidateFolder;
_fullPath = candidatePath;
_loaded = true;
return assem;
}
}
catch (Exception err) {
sb.Append(err.Message);
}
}
return null;
}
There's another solution too - it's complicated, but I've done it and done the work for you. You declare an abstract class, say MyHardwareAbstraction, that has the signatures of the methods that you want and you code against that interface. Then you write some code which given a path to an assembly, loads it and dynamically defines a new class that matches MyHardwareAbstraction and makes it map onto an instance of the actual object that you want. I wrote a blog several years ago on how to do this.
The nice thing about doing this is that you use the abstract type in your code and work against that and then the adapter compiler will, at run time, compile a new class that will complete that abstract type using some other type as the target type. It's fairly efficient too.
I you want both dll to coexist in the program, you'll have to use AppDomains, as explained here.
Else, you can simply use LoadLibrary after the user has made a clear choice about what version he needs ?
Edit:
If the intermediate DLL is a .Net Assembly, you can use the method mentioned here to specify where to look for your intermediate DLL before you call any method that uses the intermediate DLL, without having to change your existing code.
then you must not directly reference the DLL in your C# project, because .Net Assemblies are discovered and loaded before your Main method is even called. Instead, you must dynamically load the intermediate DLL using AppDomain or other methods, then use the library via reflection, or by using dynamic objects.
Apparently, this would make programming very cumbersome. However, there is an alternative method. You can write a launcher program, that loads your original application (you can load .exe files as libraries), and invokes the Main method of your original program reflectively. To make sure that the correct intermediate DLL is loaded, you can use the method mentioned here, while your launcher program is loading your original application.
The following discussion still applies to the hardware DLL.
The following is valid if:
You need only one version of the dll at a time (during the entire period your application runs), and
The two versions of the intermediate DLLs have exactly the same API.
According to MSDN, the DLL Search Path includes directories specified under the PATH environment variable. (http://msdn.microsoft.com/en-us/library/7d83bc18%28v=vs.80%29.aspx). Hence, you may put the two versions of the intermediate DLLs under seperate sub-directories under your application directory, but with exactly the same name under each directory, for example:
bin\
hardware-intermediate-v1\
intermediate.dll
hardware-intermediate-v2\
intermediate.dll
Then, at start up, after your application has determined which version to use, you may add one of the above directories to your PATH environment variable,
using System;
using System.Reflection;
using System.IO;
...
Environment.SetEnvironmentVariable(
"PATH",
Environment.GetEnvironmentVariable("PATH") + ";" +
Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) +
"\\hardware-intermediate-v1"
);
Then, calls to P-Invoke methods (DLLImport) will result in the corresponding version of the DLL to be loaded. To immediately load all DLLs, you may refer to DllImport, how to check if the DLL is loaded?.
However, if you wish to use the two version of the DLLs together without restarting your application, or if there are any API difference between the two DLLs on the level of method name and/or parameter count/type, you must create two seperate sets of P-Invoke methods, each binding to its corresponding version of the intermediate DLL.

C# How to correctly unload the class from memory?

I'm developing a solution where a service runs continuously in background, and plugin DLLs can be added/deleted at runtime. The service would load the necessary plugins when needed, run them and unload them. This is the unloading part is what currently gives me trouble: once certain class is successfully loaded first time (variable tc), it never is reloaded, even though the DLL file is updated. I think I am not unloading the class/assembly/appdomain properly, so I'd appreciate some advice for walking this last mile.
Edit: I updated the post to reflect the recent changes in code and explain when exactly the unloading has no effect: the problem does not appear on Linux Ubuntu (via Mono), but it is present on Windows 2008 Server, when I am trying to replace a certain plugin DLL with a newer file version. It seems that .NET framework has cached somewhere the assembly and is happy without reloading it. The DLL file name does not change, but the File Version property is different, so I'd expect the runtime to compare the previously loaded DLL version with the one being loaded and in case of different version numbers use the newer version. If I change the code slightly to load the assembly from a DLL file with different name, the reloading happens as expected.
using System;
using System.Reflection;
namespace TestMonoConsole
{
public interface ITestClass
{
void Talk();
}
class MainClass
{
public static void Main (string[] args)
{
string pluginPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string classAssembly = "TestClass";
string className = "TestMonoConsole.TestClass";
string command = "";
do
{
try
{
System.AppDomain domain = System.AppDomain.CreateDomain(classAssembly);
string pluginAssemblyFile = pluginPath + "/" + classAssembly + ".dll";
System.IO.StreamReader reader = new System.IO.StreamReader(pluginAssemblyFile, System.Text.Encoding.GetEncoding(1252), false);
byte[] b = new byte[reader.BaseStream.Length];
reader.BaseStream.Read(b, 0, System.Convert.ToInt32(reader.BaseStream.Length));
domain.Load(b);
reader.Close();
ITestClass tc = (ITestClass) Activator.CreateInstance(domain, classAssembly, className).Unwrap();
tc.Talk();
System.AppDomain.Unload(domain);
}
catch (System.IO.FileNotFoundException e)
{
Console.WriteLine (String.Format("Error loading plugin: assembly {0} not found", classAssembly));
}
command = Console.ReadLine();
} while (command == "");
}
}
}
You are creating the types directly into the host domain. You need to specify the domain when using Activator.CreateInstance per http://msdn.microsoft.com/en-us/library/ms224132(v=vs.90).aspx
You are instantiating the plugin types within your own AppDomain. After implementing plugin frameworks several times, I highly suggest looking into using MEF(managed extensibility framework) as a solution since it handles these common problems of code isolation. If you don't want MEF, one way to do this is by implementing a "Remote Control" class which would act as the communicator between app domains. You could call a method on your remote class that would instantiate and run the code within the secondary app domain.
MEF Documentation
Also, instead of re-inventing this mechanism, you can utilize the Managed Add-In Framework (MAF, System.AddIn) to do this for you. Look here for a quickstart.
Types and assemblies cannot be unloaded from AppDomain.
So you need to create new AppDomain, load types, do all the stuff, and then unload that domain.
According to this MSDN article, the CLR does not use shadow copying by default. You could try to enable it by following these steps:
Create an AppDomainSetup.
In the AppDomainSetup instance set ShadowCopyFiles to true.
In the AppDomainSetup instance set ShadowCopyFilesDirectories to the directory path(s) that contain the assemblies you want to be able to ovewrite at run time. This could simply be the directory where the plug-in assembly is located.
In the AppDomainSetup instance set everything else according to your needs.
Use one of the overloads of AppDomain.CreateAppDomain that take an AppDomainSetup as an argument.
Try to replace the plug-in assembly.
The fact that it works on Mono and not on CLR (Windows) could mean that the CLI does not specify if shadow copying should be enabled by default.

How can I pass a reference type between Assemblies referencing a common DLL?

High level: I am trying to build a console app (e.g. ConsoleApp.exe) which can perform some processing on any given DLL which references a certain type defined in ConsoleApp.exe.
I decided, maybe mistakenly, that I would need a companion DLL for ConsoleApp which contained the type or types (e.g. ConsoleClass) which were intended to be referenced by arbirary DLLs. To pull this off, as I don't know of a better way, I have two projects in the ConsoleApp solution, one is a class library (Proving ConsoleApp.dll) and the other is a console application which references the class library project.
At this point, I now am able to copy my ConsoleApp.dll to another relatively unrelated project in a separate solution (e.g. OtherApp.dll), reference it, and write a method which consumes a ConsoleClass instance as a parameter.
Now, in order to arbitrarily process this OtherApp.dll, the ConsoleApp.exe loads that Assembly, instantiates the proper class in that Assembly, and then calls the proper method on that instance. Pertinent lines below hopefully provide context to how I am doing this:
Assembly.LoadFrom(path_to_OtherApp_dll);
...
var x = (dynamic)Activator.CreateInstance(type_inside_OtherApp_dll);
...
var instance = new ConsoleClass();
x.some_method_call(instance);
Ultimately this fails. It seems to be because even though the two projects (ConsoleApp.exe and OtherApp.dll) are referencing the same DLL to define ConsoleClass, the runtime still considers them to be different types.
Any thoughts?
Define the public interface. Put it to its own interface.dll.
Reference interface.dll in your plugin. Let the main class in your plugin.dll implements your interface.
Reference interface.dll in your exe.
Use Assembly.Load() or Assembly.LoadFrom() to load plugin into your exe.
Use CreateInstance() to create instance of your plugin class.
Simply cast created plugin to your interface type.
So you don't need "dynamic" or other complicated things. Just easy, go step by step as I wrote and it will work. Good luck.
Yes, this will happen when ConsoleApp.dll gets loaded twice. Once by the main app, again by a plugin, using its local copy. A type's identity is determined by the assembly it was loaded from.
It isn't that clear to me how that happened. Your first weapon of choice is Fuslogvw.exe, set it up to log all the binds. First thing to do is to doctor the plugin project and set the Copy Local property of the ConsoleApp.dll reference to False so that extra copy isn't there to get accidentally used.
Copying the plugin DLLs to the main app build folder is the never-have-trouble solution, you can load them with Assembly.Load(). Or a subdirectory with a .config file that uses the <probing> element to allow the CLR to find them.
What do you by "runtime is considering them to be of differnt type"? does setup ends with some exception of error? does method in x variable receives something it does not recognize or what?

Categories