hi all,
i'm trying to figure out a way to write an application which can delete itself.
are there API's which i can use for it, should i use the windows installer like an uninstall program?
if so then how can i use it?
or are there other ways?
Thanks in advance for your replies :D
How about DeleteFile (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/deletefile.asp)?
You can't.
The problem is that you can't delete a file that's in use. There are ways around it, have a look at this...
http://www.catch22.net/tuts/selfdel.asp
Peter.
i havent checked that page link from petezl, but why not write a batch file that del's make it pause. exit your program and run the batch file?
this might work.
Thanks for your replies.
I know a program can not actually delete ITSELF, but what i mean /meant was that it 'triggers' something which allows the program to completely be removed from the computer.
kindof like using the RunOnce entry in the registry combining with the 'del' command.
i think this is one of my best options. or perhaps calling another process which deletes mine.
The problem is usually associated with installations and there is no direct method to do this. A batch file will work but will display an error when you delete the batch file itself with itself. Another trick is to use a DOS 16 bit program that deletes the file you want and itself if this still works on later versions of Windows. There is supposed to be a setting that is handled by the OS at boot that will clean uip this type of junk but I forget how its done.
It's all explained clearly in the link that was provided earlier in this thread.
His list misses a very simple way that works on ALL version of Windows from win 3.0 to server 2003. A 16 bit DOS exe does not show an error when it deletes itself and it can delete other files as well. here is the test written in quick basic 4.5 and compiled as a 16 bit EXE file.
kill "sdel.exe"
You can have a batch file that deletes everything and then deletes itself.
This will work successfully, but will return an error due to trying to read the next line of the non-existing batch file.
But as long as you don't mind a little "Batch file not found" error message, then it's okay.
I think Hutches solution is rather elegant as it's simple and shows no errors.
Obviously 16bit dos hasn't got the deletion restraints that windows have.
Peter.
I like Hutch's method but there must be a way of notifying Windows to delete the file after it exits. I say this because, typically, uninstall.exe runs from the directory being removed and it is always removed along with the rest of the files. So there must be a way and I suspect it is via a Notify message sent to the OS.
Paul
To All,
If you use the CreateFile() API call, you can instruct windows to delete the file upon 'close of the last handle' by passing FILE_FLAG_DELETE_ON_CLOSE.
An example CreateFile invoke would look like this:
invoke CreateFile, [FileSpec], FILE_READ or FILE_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, \
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_DELETE_ON_CLOSE, NULL
Hope this helps.
Relvinian
commd db "cmd.exe /c del ",0
processinfo PROCESS_INFORMATION <>
startup STARTUPINFO <>
clbuff db 500 dup (?)
TotalCleanUp PROC
;delete registry entries
;------------------------
invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,addr regkey,0,KEY_SET_VALUE, addr hkey
.IF eax!=0
invoke RegCloseKey,hkey
ret
.ENDIF
invoke RegDeleteValue,hkey,addr ProcName
invoke RegCloseKey,hkey
;remove the program itself
;-------------------------
invoke GetCommandLine
mov ComLine,eax
invoke lstrcpy,addr clbuff,addr commd
invoke lstrcat,addr clbuff,ComLine
mov startup.wShowWindow,SW_HIDE
invoke CreateProcess,NULL,addr clbuff,NULL,NULL,FALSE,0,NULL,NULL,addr startup,addr processinfo
invoke ExitProcess,0
TotalCleanUp ENDP
this is what i have done, and it works like a charm :)
thanks for all your help guys, i have solved it now :D
Relvinian,
Thank you for that information. I thought there must be a way, just did not know how. It is very useful to know these things.
Cheers,
Paul
here goes my three ways
SelfDel PROTO
.data
szBatFile db "del.bat",0
Bat db ":kill",0dh,0ah, \
"DEL %s",0dh,0ah, \
"IF EXIST %s GOTO kill",0dh,0ah, \
" ",0
lineend db "DEL %0",0
.code
start:
invoke SelfDel
invoke WinExec, addr szBatFile, SW_HIDE
invoke ExitProcess, 0
SelfDel Proc
local hFile:DWORD
local BytesWrite:DWORD
local meltbuff[256]:byte
local batbuff[256]:byte
invoke GetModuleFileNameA, 0, addr meltbuff, 255
invoke GetShortPathNameA, addr meltbuff, addr meltbuff, 255
invoke wsprintf,addr batbuff,addr Bat,addr meltbuff,addr meltbuff
invoke lstrcat,addr batbuff,addr lineend
invoke CreateFile,addr szBatFile, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
mov hFile, eax
invoke WriteFile, hFile, addr batbuff, sizeof batbuff, addr BytesWrite, 0
invoke CloseHandle, hFile
ret
SelfDel endp
end start
;this worked on 9x/2k im not sure about xp
.data
Melt db 'Command.com /C Choice.com /C:YN /N /T:Y,5|erase ',0
.data?
meltbuff db 256 dup(?)
.code
start:
invoke GetModuleFileNameA, 0, addr meltbuff, 255
invoke GetShortPathNameA, addr meltbuff, addr meltbuff, 255
invoke lstrcat,addr Melt,Addr meltbuff
invoke WinExec, addr Melt, SW_HIDE
invoke ExitProcess,0
end start
.data
szTraywnd db "shell_traywnd",0
.data?
TheExe db 256 dup(?)
lpModule dd ?
lpProcess dd ?
dwSize dd ?
lpPID dd ?
nBytesWritten dd ?
.code
start:
invoke GetModuleFileNameA, 0, addr TheExe, 255
invoke GetShortPathNameA, addr TheExe, addr TheExe, 255
invoke GetModuleHandle,0
mov [lpModule], eax
mov edi,eax
add edi,[edi+3Ch]
add edi,4
add edi,14h
mov eax,[edi+38h]
mov [dwSize],eax
invoke FindWindow,offset szTraywnd,0
invoke GetWindowThreadProcessId, eax, addr lpPID
invoke OpenProcess,PROCESS_ALL_ACCESS, FALSE, lpPID
mov [lpProcess],eax
invoke xVirtualFreeEx, [lpProcess], [lpModule], 0, MEM_RELEASE
invoke xVirtualAllocEx, [lpProcess], [lpModule], dwSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE
invoke WriteProcessMemory, [lpProcess], eax, [lpModule], [dwSize], addr nBytesWritten
invoke xCreateRemoteThread, [lpProcess], 0, 0, offset injected_thread, [lpModule], 0, ebx
invoke ExitProcess, 0
injected_thread proc
invoke Sleep,2000
invoke DeleteFile,addr TheExe
invoke ExitThread,0
ret
injected_thread endp
end start
The second one runs on XP-HE. Interesting note, the following code:
Melt db 'Command.com /C Choice.com /C:YN /N /T:Y,5|erase ',0
... generates a false positive when scanned by AntiVir.
Paul
Quote from: illwill on March 22, 2005, 04:11:16 PM
here goes my three ways
SelfDel PROTO
.data
szBatFile db "del.bat",0
Bat db ":kill",0dh,0ah, \
"DEL %s",0dh,0ah, \
"IF EXIST %s GOTO kill",0dh,0ah, \
" ",0
lineend db "DEL %0",0
Are there any difference between lines above and lines below ?
SelfDel PROTO
.data
szBatFile db "del.bat",0
Bat db "IF EXIST %s GOTO kill1",0dh,0ah, \
"GOTO kill2",0dh,0ah, \
":kill1",0dh,0ah, \
"DEL %s",0dh,0ah, \
":kill2",0dh,0ah, \
;.......
" ",0
lineend db "DEL %0",0
Sorry for taking your time, I got it...that code above creates a loop & code below doesn't