Click here to Skip to main content
14,269,736 members

How To Make Your Application Delete Itself Immediately

Rate this:
4.28 (82 votes)
Please Sign up or sign in to vote.
4.28 (82 votes)
2 Dec 2008CPOL
A simple two line technique that can be used in just about any application

Introduction

I'm sure you've all said to yourself or someone at the office at one point or another, "<snort> You idiot. Don't you know a Windows application can't delete itself? I bet you don't even know how to type high ASCII characters using the ALT key and the number pad, gahhhh.." 

Sure, there are ways to have a file delete itself on the next reboot... And you can even resort to an external program or batch file to do the work. But I just came up with a nifty way of doing it without leaving a visible trace that the application ever existed!

Background

This was just one of those simple, random ideas that popped up into my head. Took all of about 5 minutes to whip up a quick, working demo application from conception, and the technique is applicable to almost any Windows based development platform/language. 

In fact, it's taking me longer to post this on CodeProject! But since I've never posted anything on CodeProject, I thought it'd be a fun, simple exercise. :) 

Using the Code

Please note that I cannot possibly post the code for all supported languages/frameworks/platforms where this technique will work. As you will soon see, there are only two lines required to have a program delete itself without leaving a trace. These two lines will probably vary slightly in your development environment of choice, but it shouldn't take more than a minute or two to translate the code to something that works perfect for you.

And here are those two lines of code (as noted by readers, this version doesn't work on XP).  

Process.Start("cmd.exe", 
	"/C choice /C Y /N /D Y /T 3 & Del " + Application.ExecutablePath);
Application.Exit();	  

Process.Start(...) is a .NET command that launches an application with parameters. The first parameter is the application you want to launch. The second parameter is a string containing the parameters you want to pass to the application to launch. This command, by default, does not pause and wait for the launched application to finish before moving on to the next command. That next command just happens to be Application.Exit().  In .NET land, that causes the currently running application to completely shutdown. Meanwhile, our command window has popped up and is merely waiting 3 seconds for the calling application to fully close. Once that happens, the Del command comes into play and blows away the application just prior to the command window closing on its own!

The following is a description of what those parameters mean.  

  1. Cmd /C causes a command window to appear and run the command specified.. it then causes the window to close automatically.
  2. Choice /C Y /N /D Y /T 3 displays an empty, flashing prompt. However, the /T 3 means that the prompt will automatically select the default choice Y (/D Y) after 3 seconds. I didn't know about the “choice” command until a few minutes before writing this article.
  3. & is used to chain multiple commands together on a single line in a batch file. I didn't know about & until just now either.
  4. Del <Application.ExecutablePath>... Well, I'm sure you can imagine what that does. Everything after the & can be replaced with anything you want to happen after the three second delay. You could have the command delete every file within the directory...or maybe something a little more malicious? :) 

 Here's another flavor of the same thing that works on XP:

Process.Start("cmd.exe", "/C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del " + 
          Application.ExecutablePath); 
Application.Exit();

This is fairly similar to the previous version except it uses the ping command to do the dirty work. -n 1 tells the command to only ping one time and -w 3000 tells the command to wait 3 seconds before performing the ping. > Nul basically just hides the output of the ping command.

That's all, folks! You can place this code anywhere in your application, including the OnClosed event of your WinForms application.

Points of Interest

Several people have pointed out that this won't work if, for some reason, your application takes longer to shut down than what the timeout period is configured to. If you need a more fool proof technique, you might consider extending the timeout period and/or using the "delete on reboot" registry value.

Also, Filip Geens included code to hide the command prompt window from view...

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); 

If you find this code interesting, or if you know of a different technique that has the same benefits as this one, please let me know! Also, if you port this code to another language/platform, please post your version in the comments for others to benefit from. 

History

  • 12/2/2008 10:29:11 PM: Finished with version 1.. yee haw!  
  • 12/3/2008 10:02:51 AM: Added a version that works with XP and implemented some of the comments from readers

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

alexdresko
United States United States
No Biography provided

Comments and Discussions

 
SuggestionAn alternative if you don't like Cmd.exe (with source code) Pin
Elmue8-Jul-15 6:38
memberElmue8-Jul-15 6:38 
If you don't like Cmd.exe there is another option:
You write a little CleanUp.exe that deletes your Uninstaller application (which must have already deleted everything except itslef).
Additionally it deletes the folder in which your application is.

The size of CleanUp.exe is only 6 kB (six kilobyte!)
You copy it into the Temp folder (See MSDN: GetTempPath()) and call it like this:

CleanUp.exe /File=C:\ProgramFiles\MyApplication\Application.exe

(without quotes!!)

Obviously you must call it elevated (AsAdmin). But when the Uninstaller application already runs elevated, CleanUp.exe will also be started elevated.

Then CleanUp.exe waits until your Unistaller application has finished and deletes 'Application.exe' and then removes the folder 'MyApplication'.

Here is the code of CleanUp.exe:
#include "stdafx.h"

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    WCHAR* u16_CmdLine = GetCommandLine();

    WCHAR* u16_Param = wcsstr(u16_CmdLine, L"/File=");
    if (!u16_Param)
        return 0; // A double click on CleanUp.exe will do no harm

    WCHAR* u16_File = u16_Param + 6;

    WCHAR  u16_Folder[MAX_PATH];
    wcscpy(u16_Folder, u16_File);

    WCHAR* u16_Slash = wcsrchr(u16_Folder, '\\');
    if (!u16_Slash)
        return 0;

    u16_Slash[0] = 0;

    for (int i=0; i<50; i++)
    {
        Sleep(100);
        DeleteFile(u16_File);

        if (RemoveDirectory(u16_Folder))
            break;
    }
    return 0;
}


And here is my code that copies CleanUp.exe to the Temp folder and starts it:

CleanUp.exe must integrated into the resources of this process.

In the file Resources.rc you must add:
IDR_CLEANUP RCDATA DISCARDABLE "res\\CleanUp.exe"

And in Resources.h you must add:
#define IDR_CLEANUP 10000
// This function executes Cleanup.exe which will delete this processes's executable and it's folder.
// This function will either return an error code or exit the process.
// The process that calls this function must run elevated. (Uninstallers normally do)
DWORD SuicideAndCleanup()
{
    WCHAR u16_Temp[MAX_PATH];
    GetTempPath(MAX_PATH, u16_Temp);

    WCHAR u16_Cleanup[MAX_PATH];
    wcscpy(u16_Cleanup, u16_Temp);
    wcscat(u16_Cleanup, L"CleanUp.exe");

    // Any tests with FILE_FLAG_DELETE_ON_CLOSE will fail because you cannot start a process on an open file.
    HANDLE h_File = CreateFile(u16_Cleanup, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
    if (h_File == INVALID_HANDLE_VALUE)
        return GetLastError();

	HRSRC   h_Cleanup = FindResource  (NULL, MAKEINTRESOURCE(IDR_CLEANUP), RT_RCDATA);
	HGLOBAL h_Res     = LoadResource  (NULL, h_Cleanup);
	DWORD u32_Size    = SizeofResource(NULL, h_Cleanup);
	BYTE* u8_Data     = (BYTE*)LockResource(h_Res);

    // Write Cleanup.exe from the resources into the file in the Temp folder.
    DWORD u32_Written;
    if (!WriteFile(h_File, u8_Data, u32_Size, &u32_Written, NULL))
        return GetLastError();

    // The file MUST be closed here otherwise CreateProcess() returns ERROR_SHARING_VIOLATION.
    CloseHandle(h_File);

    // Build a commandline like "/File=C:\Path\to\This.exe"
    WCHAR  u16_CmdLine[MAX_PATH +6];
    wcscpy(u16_CmdLine, L"/File="); // Length = 6 chars
    GetModuleFileName(0, u16_CmdLine +6, MAX_PATH);

	PROCESS_INFORMATION k_ProcInfo    = {0};
	STARTUPINFOW        k_StartupInfo = {0};
	k_StartupInfo.cb = sizeof(STARTUPINFOW);

    // Do not use ShellExecute() here which requires CoInitilize()!
    // Here the working directory MUST be set to u16_Temp otherwise a handle to this Exe's directory
    // will stay open in CleanUp.exe and when deleting the directory -> ERROR_SHARING_VIOLATION
	if (!CreateProcess(u16_Cleanup, u16_CmdLine, 0, 0, FALSE, 0, 0, u16_Temp, &k_StartupInfo, &k_ProcInfo))
		return GetLastError();

    // Suicide
    ExitProcess(0);
    return ERROR_SUCCESS;
}

The little CleanUp.exe will remain in the Temp folder, but what is a 6 kB file on a 1 Terabyte disk?
We have to pay this little price because Microsoft did not implement an API to delay delete a file.

My suggestion for Microsoft would be an API: ExitProcessAndRemoveExecutable().

modified 8-Jul-15 19:11pm.

QuestionIf your executable path contains blank spaces: Pin
BruceG10-May-15 8:08
memberBruceG10-May-15 8:08 
SuggestionIn case of a too fast cmd execution Pin
Member 1115837512-Apr-15 10:07
memberMember 1115837512-Apr-15 10:07 
Questiontaskkill /im Pin
Steven Kirkland29-Dec-14 3:02
memberSteven Kirkland29-Dec-14 3:02 
Questionis it possible to add a preset date Pin
Member 1077842527-Apr-14 4:22
memberMember 1077842527-Apr-14 4:22 
AnswerRe: is it possible to add a preset date Pin
Yonatan Arbel19-Jun-14 2:07
memberYonatan Arbel19-Jun-14 2:07 
QuestionNice article. Pin
Sivaji156530-Sep-13 18:31
memberSivaji156530-Sep-13 18:31 
QuestionHelp me with this, if you can Pin
DM-Galaxy18-Jun-13 23:31
memberDM-Galaxy18-Jun-13 23:31 
AnswerRe: Help me with this, if you can Pin
Alex DaSwagga Dresko19-Jun-13 2:43
memberAlex DaSwagga Dresko19-Jun-13 2:43 
GeneralMy vote of 4 Pin
Andre_P.12-Mar-13 15:04
memberAndre_P.12-Mar-13 15:04 
QuestionReally working on XP and Seven Pin
Pouriya Ghamary12-Apr-12 2:20
memberPouriya Ghamary12-Apr-12 2:20 
GeneralMy vote of 4 Pin
Ozan Müyesseroğlu25-Aug-11 13:22
memberOzan Müyesseroğlu25-Aug-11 13:22 
GeneralMy vote of 5 Pin
Xmen Real 13-Apr-11 22:22
professional Xmen Real 13-Apr-11 22:22 
Generalpls help Pin
stijnn_171-Aug-10 14:59
memberstijnn_171-Aug-10 14:59 
GeneralRe: pls help Pin
joepz13-Mar-14 19:12
memberjoepz13-Mar-14 19:12 
QuestionWhy the negativity? Pin
szolsztor3-Dec-09 9:08
memberszolsztor3-Dec-09 9:08 
QuestionHow to make your application delete itself immediately Pin
jonasas7-Aug-09 6:23
memberjonasas7-Aug-09 6:23 
GeneralMy vote of 1 Pin
Fahad Sadah9-Dec-08 6:16
memberFahad Sadah9-Dec-08 6:16 
GeneralRe: My vote of 1 Pin
jgauffin4-Nov-09 2:42
memberjgauffin4-Nov-09 2:42 
GeneralMy vote of 1 Pin
Hans-Werner Dietz9-Dec-08 0:42
memberHans-Werner Dietz9-Dec-08 0:42 
GeneralRe: My vote of 1 Pin
jgauffin4-Nov-09 2:43
memberjgauffin4-Nov-09 2:43 
GeneralRe: My vote of 1 Pin
Member 842426723-Nov-11 17:24
memberMember 842426723-Nov-11 17:24 
GeneralMy vote of 1 Pin
Sandeep Datta8-Dec-08 21:48
memberSandeep Datta8-Dec-08 21:48 
GeneralRe:How to make your application delete itself immediately Pin
Naveen8-Dec-08 16:53
memberNaveen8-Dec-08 16:53 
GeneralI think this has a genuine use Pin
Poiter18-Dec-08 12:27
memberPoiter18-Dec-08 12:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Article
Posted 2 Dec 2008

Stats

192.7K views
106 bookmarked