Click here to Skip to main content
Email Password   helpLost your password?

Introduction

Uninstall programs typically want to delete themselves at the end of the un-installation, but executable cannot delete itself by simply calling the DeleteFile function. By calling the Selfdestruct() function showed below before program exit, the calling executable will be destroyed as soon as possible. The method shown in this article works on all Win32 platforms and there is no need to reboot.

Using the code

Just call the Selfdestruct() function before program exit.

// this is the name of the temporary .bat file

static const char tempbatname[] = "_uninsep.bat" ;

void Selfdestruct() 
{
  // temporary .bat file

  static char templ[] = 
    ":Repeat\r\n"
    "del \"%s\"\r\n"
    "if exist \"%s\" goto Repeat\r\n"
    "rmdir \"%s\"\r\n"
    "del \"%s\"" ;


  char modulename[_MAX_PATH] ;    // absolute path of calling .exe file

  char temppath[_MAX_PATH] ;      // absolute path of temporary .bat file

  char folder[_MAX_PATH] ;

  GetTempPath(_MAX_PATH, temppath) ;
  strcat(temppath, tempbatname) ;

  GetModuleFileName(NULL, modulename, MAX_PATH) ;
  strcpy (folder, modulename) ;
  char *pb = strrchr(folder, '\\');
  if (pb != NULL)
    *pb = 0 ;

  HANDLE hf ;
  
  hf = CreateFile(temppath, GENERIC_WRITE, 0, NULL, 
              CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ;
  
  if (hf != INVALID_HANDLE_VALUE)
  {
    DWORD len ;
    char *bat ;

    bat = (char*)alloca(strlen(templ) + 
               strlen(modulename) * 2 + strlen(temppath) + 20) ;

    wsprintf(bat, templ, modulename, modulename, folder, temppath) ;

    WriteFile(hf, bat, strlen(bat), &len, NULL) ;
    CloseHandle(hf) ;

    ShellExecute(NULL, "open", temppath, NULL, NULL, SW_HIDE);
  }
}

How it works

Let's assume the executable that wants to destroy itself is located in c:\myfolder\selfdestruct.exe. The Selfdestruct() function will create following .bat in the computers temp folder and then launches it:

    :Repeat
    del "c:\myfolder\selfdestruct.exe"
    if exist "c:\myfolder\selfdestruct.exe" goto Repeat
    rmdir "c:\myfolder"
    del "c:\temp\_uninsep.bat" ;

The .bat file will try to delete the c:\myfolder\selfdestruct.exe over and over until it finally succeeds (that is as soon as selfdestruct.exe has finished execution. Then it tries to remove the containing folder (here c:\myfolder) which will work only if it is empty and finally deletes itself. Fortunately .bat files can delete themselves.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralWhat is this templ?????????????
RAJEEV_RSD
0:05 25 Sep '09  
Hello Sir,
I'm Stuck with your code, it says that templ is undefined, in the following code.

"if (hf != INVALID_HANDLE_VALUE)
{
DWORD len ;
char *bat ;

bat = (char*)alloca(strlen(templ) +
strlen(modulename) * 2 + strlen(temppath) + 20) ;

wsprintf(bat, templ, modulename, modulename, folder, temppath) ;

WriteFile(hf, bat, strlen(bat), &len, NULL) ;
CloseHandle(hf) ;

ShellExecute(NULL, "open", temppath, NULL, NULL, SW_HIDE);
}
"

Can you please explain it to me, I appreciate your code, but one more thing, its fine that you use loop to check whether the file is deleted or not, but tell me if by any reason the file termination failed, then the whole code will run indefinately.

Instead of this, is there any way by which we can pause it for a specified time say some around 3-5 seconds, till then the program will finish completion and quits.

Waiting for Response,
GeneralRe: What is this templ?????????????
Michael Walz
0:44 25 Sep '09  
templ is defined at the beginning of the Selfdestruct() function.
Generalbat file
tetadenovicia
8:09 26 Jun '08  
You can use KILL after the last line of batch file
QuestionSelf-Destructing Files
tao1
11:56 7 May '08  
We Are Developing A Charity Site
For Film / TV / VIDEO / MUSIC / RADIO
We Are Very Much In Need Of A Simple Way
To Create An MP3 File That Will Erase Itself After One Play
Thus A Form Of Executable File That Runs A Small Player
To Play A Song Once And Then Self Destruct
This Is To Help Musicians And Producers
Who Create Work Based On Promises To Pay
And Who Send Demo MP3s To Prove Completion Of Work
And Then The Demo Is Taken Off And Used
And The Artist Is Never Reimbursed

The Site Is

www.t-film.org

In Early Phases Of Development

Manifest Communication

Manifest Respect
Manifest Peace
Manifest Love

Vector Outbound
GeneralHere's another safe and simple way
Paul Sanders (AlpineSoft)
8:02 20 Oct '07  
I don't like the batch file idea much because it 'busy-loops'. The way I self-destruct (so to speak) is to copy my 'cleanup' program to the Windows temporary directory and then run it from my uninstaller. You can probably guess the rest.

The point is that the copy in the temporary directory will go away when the user (or Windows) runs 'Disk Cleanup', and if it's just a titchy little 'delete that there folder' program, it hardly matters anyway. Windows leaves so much cr@p in the temporary directory that another few kb is unlikely to break the camel's back.



QuestionIssue with deleting the directory
ccoffman97
6:52 29 Dec '06  
So I've built this function into a sample project, but it doesn't seem to delete the the directory that it was stored in. I've put a check in the batch file that checks if the directory exists, and if it does, then try to delete it again. When I run the program, the exe is deleted, but the batch files gets stuck in the continuous loop that I've createdFrown Obviously not a good thing. When you use Process Explorer, it looks like the cmd.exe that is running has a handle open to the directory that it is trying to delete. Any ideas on how to close that handle? If you cancel out of the batch file and then just open the batch file, works flawlessly...but need it to work by being launched from the exe.

Source code:

/*This is to test the use of a batch file to delete running exe, as well as the directory that it
is stored in.

Selfdestruct function was pulled from
http://www.codeproject.com/file/cpselfdestruct2.asp
*/

#include #include #include
void Selfdestruct();
static const char tempbatname[] = "cleanup.bat" ;

void main(void)
{
Selfdestruct();

}

void Selfdestruct()
{
// temporary .bat file
static char templ[] =
":Repeat\r\n"
"del \"%s\"\r\n"
"if exist \"%s\" goto Repeat\r\n"
":Repeat2\r\n"
"rmdir \"%s\"\r\n"
"if exist \"%s\" goto Repeat2\r\n"
"del \"%s\"";

char modulename[_MAX_PATH] ; // absolute path of calling .exe file
char temppath[_MAX_PATH] ; // absolute path of temporary .bat file
char folder[_MAX_PATH] ;

GetTempPath(_MAX_PATH, temppath) ;
strcat(temppath, tempbatname) ;

GetModuleFileName(NULL, modulename, MAX_PATH) ;
strcpy (folder, modulename) ;
char *pb = strrchr(folder, '\\');
if (pb != NULL)
*pb = 0 ;

HANDLE hf ;

hf = CreateFile(temppath, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ;

if (hf != INVALID_HANDLE_VALUE)
{
DWORD len ;
char *bat ;

bat = (char*)alloca(strlen(templ) +
strlen(modulename) * 2 + strlen(temppath) * 4) ;
/*bat = (char*)alloca(strlen(templ) +
strlen(modulename) * 2 + strlen(temppath) + strlen(folder) + 20) ;*/


wsprintf(bat, templ, modulename, modulename, folder, folder, temppath) ;

WriteFile(hf, bat, strlen(bat), &len, NULL) ;
CloseHandle(hf) ;
ShellExecute(NULL, "open", temppath, NULL, NULL, SW_SHOW);
return;
}
}
AnswerRe: Issue with deleting the directory
SF1234
17:43 20 Feb '07  
Has anyone figured out this problem? I would like it so it will just delete the directory when done. Because it is not doing this now I have created a runonce registry entry to delete the directory on the next reboot but if someone has solved this I would much rather not do this.

Any ideas?



GeneralRe: Issue with deleting the directory
ccoffman97
4:09 21 Feb '07  
Haven't figured out this issue. Decided to not to worry about it because the files were being unzipped to the temporary directory, and having an empty folder in there wasn't too big of a deal. That and I have bigger fish to fry. Sorry.
QuestionModification Question
Dark_Xion
7:51 1 Oct '06  
Would there be any way for me to mod the program so that it keeps trying to delete a different file until it is no longer in use? I tried a few different methods, but none of them seemed to work, I ask because I would like to know if that would give this program the ability to be a "Delete on boot" type of program. And if it wouldn't, do you know where I could find a source code for such a thing
GeneralI wrote something like this...
Khan Shere
22:22 18 Jan '05  
void CAutoDestructOnExitDlg::AutoDestructOnExit(CString strBatchFile/*= ""*/)
{
     char exeFile[_MAX_PATH];
     char batFile[_MAX_PATH];

     GetTempPath(_MAX_PATH, batFile);
     GetModuleFileName(NULL, exeFile, _MAX_PATH);

     if(strBatchFile.IsEmpty())
     {
          char *pBuf = strrchr(exeFile, '\\');
          if(pBuf != NULL)
          {
               int iCut = pBuf - exeFile + 1;
               strBatchFile.Format("%s", &exeFile[iCut]);
               strBatchFile += ".bat";
          }
          else
               strBatchFile = "uninstallPrgFile.bat";
     }

     strcat(batFile, strBatchFile);
     FILE *file = fopen(batFile, "wt");
     if(!file)
          return;
     else
     {
          fprintf(file, ":Repeat\ndel \"%s\"\nif exists \"%s\" goto Repeat\ndel \"%s\"", exeFile, exeFile, batFile);
          fclose(file);
     }

     ShellExecute(NULL, "open", batFile, NULL, NULL, SW_HIDE);
}

I was only interested in erasing the exe file, not including the directory, and also to give the .bat file an automatic name based on the .exe name. Also, used a slighty different method in creating the file. Only one problem: the batch file is not erased Cry
GeneralRe: I wrote something like this...
Khan Shere
8:59 21 Jul '05  
fprintf(file, ":Repeat\ndel \"%s\"\nif exists \"%s\" goto Repeat\ndel \"%s\"", exeFile, exeFile, batFile);

I wrote 'exists', which is definitely wrong! The correct command is 'exist', without the 's' in the end... I spent quite some time debugging my code until I realized this was the problem. Sorry!
GeneralBug fixes and enhancements
Dennis Jiang
10:37 4 Jul '03  
1) Buffer overrun:
bat = (char*)alloca(strlen(templ) +
strlen(modulename) * 2 + strlen(temppath) + 20) ;
should be:
bat = (char*)alloca(strlen(templ) +
strlen(modulename) * 2 + strlen(temppath) + strlen(folder) + 20) ;

To prove the bug, simply use "malloc" instead of "alloca" and do a "free bat" after use.

2) To ensure the directory containing the EXE file is deleted after the file is gone, "static char templ[]" should be changed to:
static char templ[] =
"cd\\\r\n"
":Repeat1\r\n"
"del \"%s\"\r\n"
"if exist \"%s\" goto Repeat1\r\n"
":Repeat2\r\n"
"rmdir /S /Q \"%s\"\r\n"
"if exist \"%s\" goto Repeat2\r\n"
"del \"%s\"" ;
Note the two changes made to the original string:
a) We now have two Repeats
b) Added "cd\\\r\n" to the begining of the string just in case your working directory happens to be the one containing your EXE in which case "rmdir" will never succeed.

Dennis Smile
GeneralRe: Bug fixes and enhancements
amethystwu
21:23 24 Oct '05  
Two protential problems:

1) "rmdir /S /Q" is very dangerous, it will delete the folder and everything in it without prompting up messagebox for confirmation.

To prevent it, just use rmdir /Q, delete the folder only if it is empty.

2) What if the program is running in the CD-ROM or other media that cannot be modified? You will find a shell program, e.g. CMD.exe will remain in the background until next reboot. It wastes CPU time and looks like a virusUnsure

The most simple solution for it is to use GetModuleFileName() and GetDriveType() to verify whether the program is running from a CD-ROM.
GeneralOther methods
Papa
4:34 28 Apr '03  

http://freespace.virgin.net/james.brown7/tuts/selfdel.htm

Papa


while (TRUE)
Papa.WillLove ( Bebe ) ;
GeneralRe: Other methods - Clickety
Phil J Pearson
8:06 29 Apr '03  
http://freespace.virgin.net/james.brown7/tuts/selfdel.htm[^]

Papa


while (TRUE)
Papa.WillLove ( Bebe ) ;


GeneralRe: Other methods: More Methods
DoctorKoch
0:40 15 Jan '07  
The link above seems to be broken. Here some other links:

Catch22 Tutorial:
http://www.catch22.net/tuts/selfdel.asp[^]

Ragestorm Postings:
http://www.ragestorm.net/thread?id=6[^]
GeneralReally really small article HTML bug
Dominik Reichl
10:26 27 Apr '03  
There's a really small bug in the batch script in the "How it works" section of your article: batch command lines usually don't have ; at the end. The ; should be removed. Smile

(You've copied the part from the source code, hmm? Big Grin )

-Dominik



_outp(0x64, 0xAD); and
__asm mov al, 0xAD __asm out 0x64, al do the same... but what do they do?? Wink

GeneralBatch doesn't terminate
Dominik Reichl
10:16 27 Apr '03  
Hello,

thanks for your great article! Just one question: does the batch file terminate itself? I compiled a demo application several times and started it, each time I run it a "Winoldap" process hangs in the background (visible in Ctrl-Alt-Del) and doesn't terminate... It seems the batch prompt is waiting for something? Perhaps it outputs an error because the batch deletes itself (system cannot read file any more...), and nobody can answer the questions of the system... ?

-Dominik



_outp(0x64, 0xAD); and
__asm mov al, 0xAD __asm out 0x64, al do the same... but what do they do?? Wink

GeneralRe: Batch doesn't terminate
jlap777
14:45 27 Apr '03  
They disable the keyboard Wink
GeneralRe: Batch doesn't terminate
Dominik Reichl
7:45 28 Apr '03  
Hehe, yes Big Grin Big Grin Big Grin


_outp(0x64, 0xAD); and
__asm mov al, 0xAD __asm out 0x64, al do the same... but what do they do?? Wink

GeneralRe: Batch doesn't terminate
DJWALSH
3:08 28 Apr '03  
Try looking at the BAT file itself. Is it creating the correct output? For further help post both the bat file and your code if you changed it.

Never tell people how to do things. Tell them what to do and they will surprise you with their ingenuity.
- General George S. Patton
GeneralRe: Batch doesn't terminate
Dominik Reichl
7:43 28 Apr '03  
Hello,

DJWALSH wrote: Is it creating the correct output?
Yes, the Selfdestruct routine works very well, i.e. the executable is deleted and then the directory is removed. It's just there is a process hanging in the background ("Winoldap") which doesn't terminate. (I am using Windows 98, just if you need to know Smile )

DJWALSH wrote: For further help post both the bat file and your code if you changed it.
I don't have to post the BAT file, it is exactly the one listed in the article. I haven't changed anything to the Selfdestruct routine, just written a small demo application:

#include <windows.h>
#include <memory.h>
#include <string.h>
#include <malloc.h>


void Selfdestruct() ;


int main()
{
Selfdestruct();
return 0;
}


// this is the name of the temporary .bat file
static const char tempbatname[] = "_uninsep.bat" ;


void Selfdestruct()
{
// temporary .bat file
static char templ[] =
":Repeat\r\n" "del \"%s\"\r\n" "if exist \"%s\" goto Repeat\r\n" "rmdir \"%s\"\r\n" "del \"%s\"" ;


char modulename[_MAX_PATH] ; // absolute path of calling .exe file
char temppath[_MAX_PATH] ; // absolute path of temporary .bat file
char folder[_MAX_PATH] ;


GetTempPath(_MAX_PATH, temppath) ;
strcat(temppath, tempbatname) ;


GetModuleFileName(NULL, modulename, MAX_PATH) ;
strcpy (folder, modulename) ;
char *pb = strrchr(folder, '\\');
if (pb != NULL)
*pb = 0 ;


HANDLE hf ;


hf = CreateFile(temppath, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ;


if (hf != INVALID_HANDLE_VALUE)
{
DWORD len ;
char *bat ;


bat = (char*)alloca(strlen(templ) +
strlen(modulename) * 2 + strlen(temppath) + 20) ;


wsprintf(bat, templ, modulename, modulename, folder, temppath) ;


WriteFile(hf, bat, strlen(bat), &len, NULL) ;
CloseHandle(hf) ;


ShellExecute(NULL, "open", temppath, NULL, NULL, SW_HIDE);
}
}

-Dominik



_outp(0x64, 0xAD); and
__asm mov al, 0xAD __asm out 0x64, al do the same... but what do they do?? Wink

GeneralRe: Batch doesn't terminate
Michael Walz
7:50 28 Apr '03  
Try to replace
ShellExecute(NULL, "open", temppath, NULL, NULL, SW_HIDE);
by
ShellExecute(NULL, "open", temppath, NULL, NULL, SW_SHOW);

This will show the command window with the batch file running and tell me what happens.

Michael


GeneralRe: Batch doesn't terminate
Dominik Reichl
8:49 28 Apr '03  
Done. It doesn't show an error as I first thought, it's just the window of a terminated ms-dos console (window title "Beendet - _uninsep", 'Beendet' is german for completed/terminated/ended, you know Smile ). No errors or warnings.

Roll eyes
-Dominik



_outp(0x64, 0xAD); and
__asm mov al, 0xAD __asm out 0x64, al do the same... but what do they do?? Wink

GeneralRe: Batch doesn't terminate
Pater
23:23 28 Apr '03  
This could probably be fixed by using a .pif file. (With the option "Close on exit checked") But how to create one (Pif's are binary)? And how to remove that file? WTF


Last Updated 27 Apr 2003 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010