I'm creating a self updating app where I have the majority of the code in a seperate DLL. It's command line and will eventually be run on Mono. I'm just trying to get this code to work in C# on windows at the command line.
How can I create a c# application that I can delete a supporting dll while its running?
AppDomain domain = AppDomain.CreateDomain("MyDomain");
ObjectHandle instance = domain.CreateInstance( "VersionUpdater.Core", "VersionUpdater.Core.VersionInfo");
object unwrap = instance.Unwrap();
Console.WriteLine(((ICommand)unwrap).Run());
AppDomain.Unload(domain);
Console.ReadLine();
at the ReadLine the VersionUpdater.Core.dll is still locked from deletion
The ICommand interface is in VersionUpdater.Common.dll which is referenced by both the Commandline app and VersionUpdater.Core.dll
You can always use
MOVEFILE_DELAY_UNTIL_REBOOT
to delete on reboot. This is most likely the least hackey way todo this sort of thing, by hackey I ususally see things like; loading up new DLL's or injecting to explorer.exe even patching a system dll to get loaded into another process, etc...MoveFileEx From MSDN;
The only way I've ever managed something similar is to have the DLL in a separate AppDomain to the assembly that is trying to delete it. I unload the other AppDomain and then delete the DLL from disk.
If you're looking for a way to perform the update, off the top of my head I would go for a stub exe that spawns the real AppDomain. Then, when that stub exe detects an update is to be applied, it quits the other AppDomain and then does the update magic.
EDIT: The updater cannot share DLLs with the thing it is updating, otherwise it will lock those DLLs and therefore prevent them from being deleted. I suspect this is why you still get an exception. The updater has to be standalone and not reliant on anything that the other AppDomain uses, and vice versa.
Unwrap will load the assembly of the object's type into the appdomain that calls it. One way around this is to create a type in your "base" assembly that calls command.run, then load that into your new appdomain. This way you never have to call unwrap on an object from a type in a different assembly, and you can delete the assembly on disk.
When I built a self-updating app, I used the stub idea, but the stub was the app itself.
The app would start, look for updates. If it found an update, it would download a copy of the new app to temp storage, and then start it up (System.Diagnostics.Process.Start()) using a command-line option that said "you are being updated". Then the original exe exits.
The spawned exe starts up, sees that it is an update, and copies itself to the original app directory. It then starts the app from that new location. Then the spawned exe ends.
The newly started exe from the original app install location starts up - sees the temp file and deletes it. Then resumes normal execution.