The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: white scorpion on January 30, 2005, 10:10:49 PM

Title: how can i let my program delete itself if the user asks for it?
Post by: white scorpion on January 30, 2005, 10:10:49 PM
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
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: asmGhost on January 30, 2005, 10:19:53 PM
How about DeleteFile (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/deletefile.asp)?
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: hutch-- on January 30, 2005, 11:16:40 PM
You can't.
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: petezl on January 30, 2005, 11:22:41 PM
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.
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: Ash_ on January 31, 2005, 06:19:56 AM
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.
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: white scorpion on January 31, 2005, 06:56:19 AM
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.

Title: Re: how can i let my program delete itself if the user asks for it?
Post by: hutch-- on January 31, 2005, 08:32:07 AM
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.
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: Nilrem on January 31, 2005, 09:38:55 AM
It's all explained clearly in the link that was provided earlier in this thread.
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: hutch-- on January 31, 2005, 11:24:48 AM
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"
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: Tedd on January 31, 2005, 11:46:33 AM
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.
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: petezl on January 31, 2005, 12:23:20 PM
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.
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: pbrennick on January 31, 2005, 06:07:07 PM
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
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: Relvinian on January 31, 2005, 07:29:32 PM
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
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: white scorpion on January 31, 2005, 07:39:17 PM


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

Title: Re: how can i let my program delete itself if the user asks for it?
Post by: pbrennick on January 31, 2005, 09:36:08 PM
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
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: 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

.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

Title: Re: how can i let my program delete itself if the user asks for it?
Post by: pbrennick on March 22, 2005, 06:41:49 PM
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
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: ramguru on December 12, 2006, 01:46:47 PM
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
Title: Re: how can i let my program delete itself if the user asks for it?
Post by: ramguru on December 12, 2006, 01:59:20 PM
Sorry for taking your time, I got it...that code above creates a loop & code below doesn't