Self deletable application in C# in one executable

If you use Process.Start you can pass in the Del parameter and the path to the application you wish to delete.

ProcessStartInfo Info=new ProcessStartInfo();
Info.Arguments="/C choice /C Y /N /D Y /T 3 & Del "+
               Application.ExecutablePath;
Info.WindowStyle=ProcessWindowStyle.Hidden;
Info.CreateNoWindow=true;
Info.FileName="cmd.exe";
Process.Start(Info); 

Code snippet taken from this article


I suggest you use a batch file as a bootstrap and have it delete itself and the exe afterwards

public static class Updater
{
    public static void Main() 
    {   
        string path = @"updater.bat";

        if (!File.Exists(path)) 
        {
            // Create a file to write to.
            using (StreamWriter sw = File.CreateText(path)) 
            {
                sw.WriteLine("updater.exe");
                sw.WriteLine("delete updater.exe /y");
                sw.WriteLine("delete updater.bat /y");
            } 

            System.Process.Start(path);   
        }
        else
        {
            RunUpdateProcess();
        }
    }

    private void RunUpdateProcess()
    {
        .....
    }
}

It's tricky without introducing yet another process (that you'd then want to delete as well, no doubt). In your case, you already have 2 processes - updater.exe and application.exe. I'd probably just have the Application delete updater.exe when it's spawned from there - you could use a simple command line arg, or an IPC call from updater.exe to application.exe to trigger it. That's not exactly a self deleting EXE, but fulfills the requirements I think.

For the full treatment, and other options you should read the definitive treatment of self deleting EXEs. Code samples are in C (or ASM), but should be p/invokable.

I'd probably try CreateFile with FILE_FLAG_DELETE_ON_CLOSE for updater.exe with something like (psuedo code):

 var h = CreateFile(
            "updater.exe", 
            GENERIC_READ | GENERIC_WRITE, 
            FILE_SHARE_DELETE, 
            NULL, 
            CREATE_NEW, 
            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE
         );

 byte[] updaterBytes = GetUpdaterBytesFromWeb();
 File.WriteAllBytes("updater.exe", updaterBytes);

 Process.Start("updater.exe");

Once application.exe exits, updater.exe has a file handle of 1. When updater.exe exits, it drops to 0 and should be deleted.


Couldn't you simply delete the updater from within the application? i.e.:

Application: Start -> [Delete old updater if present] -> Check version -> Download new updater -> Start updater -> exit;

Updater: Start -> Perform update -> Start application -> exit;

Application: Start -> [Delete old updater if present] -> ...