|
Hello Michael,
Actually i was trying your code but i am stuck at one place, my folder don't get deleted. Ihaven't used repeat loop as it is crashing the application...
THis is the code that i am using.....
CString templ =
"del \"%s\"\r\n"
"taskkill /im selfdelete.exe\r\n"
"del \"%s\"\r\n"
"rmdir /S /Q \"%s\"\r\n"
"del \"%s\"" ;
what can i do for it.... i am using visual studio 2008 and vista..
thanks in advance....
and yes your code was very usefull and easy to understand
|
|
|
|
|
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,
|
|
|
|
|
templ is defined at the beginning of the Selfdestruct() function.
|
|
|
|
|
You can use KILL after the last line of batch file
|
|
|
|
|
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
|
|
|
|
|
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.
|
|
|
|
|
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 created 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 <windows.h>
#include <tchar.h>
#include <malloc.h>
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;
}
}
|
|
|
|
|
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?
|
|
|
|
|
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.
|
|
|
|
|
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
|
|
|
|
|
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
|
|
|
|
|
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!
|
|
|
|
|
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
|
|
|
|
|
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 virus
The most simple solution for it is to use GetModuleFileName() and GetDriveType() to verify whether the program is running from a CD-ROM.
|
|
|
|
|
http://freespace.virgin.net/james.brown7/tuts/selfdel.htm
Papa
while (TRUE)
Papa.WillLove ( Bebe ) ;
|
|
|
|
|
|
|
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.
(You've copied the part from the source code, hmm? )
-Dominik
_outp(0x64, 0xAD);
and
__asm mov al, 0xAD __asm out 0x64, al
do the same... but what do they do??
|
|
|
|
|
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??
|
|
|
|
|
They disable the keyboard
|
|
|
|
|
Hehe, yes
_outp(0x64, 0xAD);
and
__asm mov al, 0xAD __asm out 0x64, al
do the same... but what do they do??
|
|
|
|
|
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
|
|
|
|
|
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 )
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>
<br><br>
void Selfdestruct() ;
<br><br>
int main()
{
Selfdestruct();
return 0;
}
<br><br>
static const char tempbatname[] = "_uninsep.bat" ;
<br><br>
void Selfdestruct()
{
static char templ[] =
":Repeat\r\n"
"del \"%s\"\r\n"
"if exist \"%s\" goto Repeat\r\n"
"rmdir \"%s\"\r\n"
"del \"%s\"" ;
<br><br>
char modulename[_MAX_PATH] ;
char temppath[_MAX_PATH] ;
char folder[_MAX_PATH] ;
<br><br>
GetTempPath(_MAX_PATH, temppath) ;
strcat(temppath, tempbatname) ;
<br><br>
GetModuleFileName(NULL, modulename, MAX_PATH) ;
strcpy (folder, modulename) ;
char *pb = strrchr(folder, '\\');
if (pb != NULL)
*pb = 0 ;
<br><br>
HANDLE hf ;
<br><br>
hf = CreateFile(temppath, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ;
<br><br>
if (hf != INVALID_HANDLE_VALUE)
{
DWORD len ;
char *bat ;
<br><br>
bat = (char*)alloca(strlen(templ) +
strlen(modulename) * 2 + strlen(temppath) + 20) ;
<br><br>
wsprintf(bat, templ, modulename, modulename, folder, temppath) ;
<br><br>
WriteFile(hf, bat, strlen(bat), &len, NULL) ;
CloseHandle(hf) ;
<br><br>
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??
|
|
|
|
|
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
|
|
|
|
|
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 ). No errors or warnings.
-Dominik
_outp(0x64, 0xAD);
and
__asm mov al, 0xAD __asm out 0x64, al
do the same... but what do they do??
|
|
|
|
|