Hello Peeps.... i'm working on a prog so that when it detects something it deletes itself, i am not using any windows so i guess WM_DESTROY is out. I used

DeleteFile, addr FileName
ExitProcess, NULL

where FileName is the name of my program..... But it doesn't work, anyone have any ideas? Thanks a lot :)
Posted on 2002-04-05 05:34:55 by Tsongkie[ii]
What you want is not easy. As windows uses the executable file because your program is running, you can't delete it while it's running.
There have been several tricks to do this but they all work differently on different OSes.
http://www.asmcommunity.net/board/index.php?topic=4190&highlight=delete+process

Thomas
Posted on 2002-04-05 06:33:53 by Thomas
Tsongkie,

My own approach is to create a small dos COM or EXE file that deletes what you want then itself. You can store it in the 32 bit EXE file and run it as the exit command with WinExec or CreateProcess.

There is a prog in MASM32 called bintodb.exe that will convert and existing file to asm DB format.

Regards,

hutch@movsd.com
Posted on 2002-04-06 01:41:31 by hutch--
1)
The MoveFileEx method:
I'm going to mention this technique even though it doesn't really solve your problem, because it's quite useful to know and can be handy in other situations.

MoveFileEx(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, DWORD dwFlags);

This API call moves a file to a new location. When you pass NULL as the second parameter, this causes the file to be moved "nowhere", effectively deleting the file. Now, ordinarily this would fail if you tried this with the path to the current executable. However, if we specify MOVEFILE_DELAY_UNTIL_REBOOT in the dwFlags parameter, this tells Windows not to move (or delete) the file until the system is shutdown or rebooted.

There are a few problems with this technique. Firstly, you cannot remove the directory that the executable resides in. Second, the file is not deleted immediately - if your system doesn't get rebooted very often, then the file will stay around. But the biggest problem is that MoveFileEx is not implemented on Windows 95/98/ME.

2)
The WININIT.INI method:
Under Windows 95/98/ME, an application called WININIT.EXE runs each time the system is started. This application looks for a file called WININIT.INI. If this file exists, WININIT.EXE looks for a section called . Each entry in the section specifies a file rename operation which will occur (once) when time the system starts. This method is obviously very similar to the MoveFileEx method described above.


NUL=c:\dir\myapp.exe
c:\dir\new.exe=c:\dir\old.exe

The filename to the left of the equal sign specifies the new name of the filename on the right. When NUL is used as the new filename, the file is deleted. This means that an application can write an entry into WININIT.INI, specifying NUL and the applications own full path.

You must be careful when writing an entry to the section. You cannot use WritePrivateProfileString API call, because this function prevents any duplicate entries from occuring under the same section. This restriction would prevent there from being more than one "NUL=" entry. Therefore you must manually write any entry if you want to use this technique.

3)
The Self-Deleting Batch File method:
This is quite a well known method, and was documented in MSDN some time ago. This technique works on both Windows 95 and Windows NT. It works because MS-DOS batch files are able to delete themselves. To test this technique, create a small batch file containing the single command:

del %0.bat
The batch file, when run, deletes itself and issues an error "The batch file cannot be found". This error is just a simple message, so it can be safely ignored. By itself this isn't too useful, but when modified to delete our executable it solves our problem, albeit in a rather forceful manner. Our executable will create a batch file (called DelUs.bat) with the following content:

:Repeat
del "C:\MYDIR\MYPROG.EXE"
if exist "MYPROG.EXE" goto Repeat
rmdir "C:\MYDIR"
del "\DelUS.bat"
This batch file repeatedly attempts to delete the specified file, and will run continuously consuming CPU until it succeeds. When the execuable has been deleted, the batch file then deletes itself.

The executable needs to spawn off the batch file using CreateProcess, and then should exit immediately. It would be a good idea to give the batch file's thread of execution a low priority so that it doesn't get much execution time until the original executable has terminated.

4)
The DELETE_ON_CLOSE method:
The CreateFile API call accepts several flags which affect how a file is created or opened. One of these flags, FILE_FLAG_DELETE_ON_CLOSE, specifies that the file will be deleted when the last handle to it is closed. The basis to this technique will be to run an executable with this flag set, so that when it exits, it is deleted automatically.

The first step is to create an empty file with the DELETE_ON_CLOSE flag specified. The exact binary content of the current executable file is then copied into this new file, in effect duplicating the executable on disk. A new process is then created (using the new executable file). This has the effect that the duplicate file's handle count is incremented. Also, when the new process was created, the full path of the current process was passed through the command-line argument.

Next, the current executable (which wants to delete itself) closes the file handle used to create the new process, and then exits. Now, the duplicate's file-handle count is decremented, but because CreateProcess incremented its handle count when it started, the file is not deleted.

At this point, the duplicate executable has started running. The PID specified on the command-line is used to open a handle to the original process. The duplicate waits for the original process to terminate, using WaitForSingleObject. When this call returns, the duplicate can call DeleteFile on the filename also specified through its command-line argument. The original executable (the one that wanted to delete itself) has been successfully deleted. This just leaves the duplicate copy, which exits normally. The duplicate's file-handle count drops to zero, the DELETE_ON_CLOSE flag comes into effect, and the duplicate file is deleted also.

It sounds a bit complicated, but it's not too difficult. Here's the steps one more time:

[ Current process ]
1. Create a new file with FILE_FLAG_DELETE_ON_CLOSE.
2. Copy the current executable's content into the new file.
3. Create a new process with the duplicate executable:
4. Pass the current executable's full path and PID in the call to CreateFile.
5. Sleep for a short time to give the new process time to start.
6. Close the new file.
7. Exit current process.

[ Duplicate process ]
8. Wait for the process specified on command-line to die.
9. Delete file specified on command-line.
10. Exit duplicate process.
There are just a couple of technicalities to mention. First, when the "new" process is spawned, the "old" process must sleep for a short period, enough to let the Windows loader open the file and create the process (thus incrementing it's file count).

Second, the new process must wait until the old process terminates, which releases its file count.

Third, when the duplicate executable is created, it must also have the FILE_SHARE_DELETE flag specified, otherwise CreateProcess will fail, because it won't be able to open the file whilst we have it open with the DELETE_ON_CLOSE flag set.

Obviously this method will require careful coding, because the program must be written in such a way so that it can perform these dual tasks. The "new" executable must know that it's job is to delete the file specified on the command line, for instance.

It's a little messy, but it does work very well. In fact, the uninstall program that I wrote, which is included with the software you can download from this site, uses this very method. I've included an example program which demonstrates this technique.

An alternative method is to write a very small stand-alone executable, which it's sole task is to delete the file-name specified on it's command-line. This executable could then be imbedded as a "payload" to the executable which wants to delete itself. This payload would be created and executed in the same way as described above.

5)
The Ultimate Self-Deleting Executable: (NT only)
I thought I'd save the best until last. This inline assembly snippet is short and simple. I can't claim credit for this code - I found it posted on usenet some time ago. The author's name is Gary Nebbett.

lea eax, buf
push 0
push 0
push eax
push ExitProcess
push module
push DeleteFile
push UnmapViewOfFile
ret

This snippet ONLY works under Windows NT, but it works like a dream. As soon as you compile and run the above program, it just disappears from disk!

Have fun! :alright:
Posted on 2002-04-09 13:10:55 by Graebel
Never got the FILE_FLAG_DELETE_ON_CLOSE method working.
The "push push push ret" thingy only works on *some* NT versions,
and depends on a *lot* of undocumented (thus unreliable) behaviours.
Self-deleting batch files usually leave a console window after they're
done, and on 9x sometimes a WINOLDAP process.

I prefer leaving a small "do the final stuff" executable in the user's
temp dir, and add a delete command for it in runonce or whatever.
Large installers like installshield and whatnot leave a *LOT* of crap
behind, so I think it's okay for me to put a smallish (say 16kb if coded
sloppily) executable behind, which will disappear on next boot.
Posted on 2002-04-09 13:41:01 by f0dder
Looking at the alternatives, now I know why I use a DOS executable or COM file to delete the required app then itself. Leaves nothing behind, is not version specific and is hassle free.

Regards,

hutch@movsd.com
Posted on 2002-04-10 08:44:12 by hutch--