Executing and then Deleting a DLL in c# - mono

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

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.

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;
lpNewFileName [in, optional] The new
name of the file or directory on the
local computer.
When moving a file, the destination
can be on a different file system or
volume. If the destination is on
another drive, you must set the
MOVEFILE_COPY_ALLOWED flag in dwFlags.
When moving a directory, the
destination must be on the same drive.
If dwFlags specifies
MOVEFILE_DELAY_UNTIL_REBOOT and
lpNewFileName is NULL, MoveFileEx
registers the lpExistingFileName file
to be deleted when the system
restarts. If lpExistingFileName refers
to a directory, the system removes the
directory at restart only if the
directory is empty.

Related

Shadowcopy of AppDomain does not updating referenced dll

We have a main application (Winforms) with several dll's referenced containing Logic and UI Layers. After some research on how to perform auto-update in a winforms application, I found a solution using AppDomain and the ShadowCopies feature.
Another executable look for updates and makes the exchange of files.
Okay, but now, I got the following situation:
I start the main application (loaded through the new AppDomain).
I open a form that is in a referenced dll ("ReferenceA"). This dll is copied and instantiated from the copy. (Great!)
At this time the system receives an update with new versions of "ReferenceA" and "ReferenceB", and makes the exchange of files.
I open another form that is in "ReferenceB". This dll is copied and instantiated from the copy, but this dll also references "ReferenceA" that is not updated by ShadowCopy because it is already in the directory.
Now the system is running a newer version of "ReferenceB" with an older version of "ReferenceA". In my test I created a new method in "ReferenceA" then I obviously got the message: "Method not found".
Any suggestions on how I can solve this?

How to compile to a single release exe from VS2012 without installer

I realise similar questions have previously been asked but nobody really seems to get to the bottom of it.
I am developing in a work environment where policy restrictions prevent users from installing software on their computers. I have created a VB project and am compiling the release to distribute but I just want a clean single .exe file, which I can put in a folder on a network drive and people can access at will.
Whenever I compile, I get the background files externally from the exe (vshost, config, manifest etc.).
My end users are not tech savvy, and are never really sure which file to open. Now, save creating a shortcut and hiding the program files away, is there another way of creating a single, rolled up, all-in-one, exe file for distribution?
You don't really need the other files (maybe only the .pdb depending on what kind of application you've made, and what code you use). Just copy the output .exe to the drive and it should be fine, IF it doesn't use any special dlls.
You need to add this code after registerign Form Close Event
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
foreach (var name in System.IO.Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory))
{
if (name.Contains("manifest") || name.Contains(".pdb"))
System.IO.File.Delete(name);
}
}
You also need to close Visual Studio Window

Is it possible to create a file that is deleted when its (owning) process goes away?

I want to create a file on Mac OS X (10.6) that will be deleted automatically when my process goes away. Is this possible? It would be very handy for a file locking scheme I am implementing. Preferably as a Cocoa or Carbon call.
I know that on Windows, this is possible. It's a very neat feature, but I don't know if it is something that needs to be supported by the file system.
On win32 you can call CreateFile with FILE_FLAG_DELETE_ON_CLOSE.
In .net you can create a FileStream with FileOptions.DeleteOnClose as argument.
If you are writing your own program, you could use tmpfile() call.
It creates a temporary file that get removed automatically on program termination.
You could have your app delegate to create and delete the file via the NSApplicationDelegate, however, the file would remain there if the user force quits/shut down. If force quitting is not part of your concern, then this should work. If not, you can create a simple launch agent that checks if your process exists, and if not, delete the file.
You can register an atexit() handler to delete the file, but this will not necessarily be completely reliable, particularly if the program crashes.
If you want proper file locking, consider using flock(), although, it is cooperative.

File system operations (e.g. copy, delete, move) performed through ActiveSync - are they atomic?

I am developing an application in .NET Compact Framework 3.5, for Windows CE 6. I need to automate some data synchronization between the mobile application and a PC. So what I do is that, in the .NETCF application, I have a while loop that checks every few seconds, using System.IO.File.Exists(fullFilePath), whether the file I am expecting has been copied from the PC to the mobile device, through an ActiveSync connection.
Once the mobile app finds the file, it will open and read it using a StreamReader.
My problem is that, some times, File.Exists(fullFilePath) would return true, yet the subsequent use of StreamReader may fail with a FileNotFoundException.
Ruling out the possibility of the file getting deleted between the call to File.Exists() and the instantiation of the StreamReader, would anybody know how the exception may occur? Is it because file copy through ActiveSync is not atomic, such that the file is not actually ready for reading even though File.Exists() returns true?
A file copy is most certainly not going to be atomic. When you start the copy, the file is created, but has no data in it. As the file data gets written, the file "exists", but is not yet fully complete. You'd want to know not only that it exists, but that it's not currently in use (meaning the writer is done). Trying to open it exclusively would verify that.

Is there a way to change referenced library files during processing?

I have a .NET customer framework that functions much like a Workflow. It uses reflection to get a listing of all of the processes it is capable of from a specific folder, and starts them via reflection with a known start point (all of them have a method called "Process"). Since these files are only called to do the processing and not part of the compile... is there a way for me to be able to drop in a new reference library (DLL) for one of the processes that is being updated without restarting the whole process?
Here is my flow...
START
Load list of references
Load work, assign to references
After X Time, refresh references (or
on WCF refresh command being sent)
Is it possible to do this, or do I do I need to actually stop and restart the assembly base to be able to recognized the new reference file?
Yes you can with Assembly.Load but I think you need to look at MEF first.