0

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?

Jackdaw
  • 7,626
  • 5
  • 15
  • 33
Vamshi
  • 3
  • 4
  • 1
    You will need to close the process that is using that DLL, I asume that is your program, then you need to stop and then replace and start the program again. If a file is being used by a process you can't delete/replace it – Camadas Jun 17 '22 at 12:03
  • Camadas, how can i make it as a code? – Vamshi Jun 17 '22 at 12:19
  • You can have a extra .exe, to take care of the replacement. For example you can call that exe and exit the main program, then replace the dll with that extra .exe and start the program again from there. Don't remenber how, but did something similar a few years ago, when the main program would verify if there was a new version to download, if I would click update it would close the main program, call the update.exe, to download all the new stuff and start the program again at the end – Camadas Jun 17 '22 at 12:25
  • Does there's another way? – Vamshi Jun 17 '22 at 12:29
  • Well a little search on stack, https://stackoverflow.com/questions/30441430/load-and-replace-dll-application Check the anwser from Bradley – Camadas Jun 17 '22 at 12:31

2 Answers2

0

One of possible solutions.

Note: in this solution constructor must be parameterless. Logic with input parameters must be separated to Initialize() method.

  1. Separate all models/interfaces/enums etc. from project "a" to another project (let's call it "Models").
  2. Make reference from Models to both project a and your executable project.
  3. Remove reference from a to your executable project (but make sure that your a.dll will be placed in same folder as executable).
  4. 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.

Andrii Khomiak
  • 565
  • 4
  • 17
0

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
Blindy
  • 65,249
  • 10
  • 91
  • 131