最近 需要实现程序自删除功能,在网上看到一段代码 如下:#include "stdafx.h"
#include <Windows.h>
#include <stdlib.h>
#include <tchar.h>
int main(int argc, char* argv[])
{
if (argc == 1)
{
// Original EXE: Spawn clone EXE to delete this EXE
// Copy this EXEcutable image into the user's temp directory
TCHAR szPathOrig[_MAX_PATH], szPathClone[_MAX_PATH];
GetModuleFileName(NULL, szPathOrig, _MAX_PATH);
GetTempPath(_MAX_PATH, szPathClone);
GetTempFileName(szPathClone, __TEXT("Del"), 0, szPathClone);
CopyFile(szPathOrig, szPathClone, FALSE);
//***注意了***:
// Open the clone EXE using FILE_FLAG_DELETE_ON_CLOSE
HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
// Spawn the clone EXE passing it our EXE's process handle
// and the full path name to the Original EXE file.
TCHAR szCmdLine[512];
HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE, TRUE, GetCurrentProcessId());
wsprintf(szCmdLine, __TEXT("%s %d \"%s\""), szPathClone, hProcessOrig, szPathOrig);
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
CloseHandle(hProcessOrig);
CloseHandle(hfile);
// This original process can now terminate.
}
else
{
// Clone EXE: When original EXE terminates, delete it
HANDLE hProcessOrig = (HANDLE) _ttoi(__targv[1]);
WaitForSingleObject(hProcessOrig, INFINITE);
CloseHandle(hProcessOrig);
DeleteFile(__targv[2]);
}
return(0);
}结果是 主程序删除了 temp文件夹下的那个临时文件 没有删除,哪位大神看看是个什么因为,谢谢了VCEXE
#include <Windows.h>
#include <stdlib.h>
#include <tchar.h>
int main(int argc, char* argv[])
{
if (argc == 1)
{
// Original EXE: Spawn clone EXE to delete this EXE
// Copy this EXEcutable image into the user's temp directory
TCHAR szPathOrig[_MAX_PATH], szPathClone[_MAX_PATH];
GetModuleFileName(NULL, szPathOrig, _MAX_PATH);
GetTempPath(_MAX_PATH, szPathClone);
GetTempFileName(szPathClone, __TEXT("Del"), 0, szPathClone);
CopyFile(szPathOrig, szPathClone, FALSE);
//***注意了***:
// Open the clone EXE using FILE_FLAG_DELETE_ON_CLOSE
HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
// Spawn the clone EXE passing it our EXE's process handle
// and the full path name to the Original EXE file.
TCHAR szCmdLine[512];
HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE, TRUE, GetCurrentProcessId());
wsprintf(szCmdLine, __TEXT("%s %d \"%s\""), szPathClone, hProcessOrig, szPathOrig);
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
CloseHandle(hProcessOrig);
CloseHandle(hfile);
// This original process can now terminate.
}
else
{
// Clone EXE: When original EXE terminates, delete it
HANDLE hProcessOrig = (HANDLE) _ttoi(__targv[1]);
WaitForSingleObject(hProcessOrig, INFINITE);
CloseHandle(hProcessOrig);
DeleteFile(__targv[2]);
}
return(0);
}结果是 主程序删除了 temp文件夹下的那个临时文件 没有删除,哪位大神看看是个什么因为,谢谢了VCEXE
[ 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.
我下载了他的例子来试过了,他那个FILE_FLAG_DELETE_ON_CLOSE的例子也是删不掉临时文件的
http://www.catch22.net/sites/default/files/selfdel.zip
#include <windows.h>
#include <tchar.h>#pragma comment (linker, "/NODEFAULTLIB")#ifndef _DEBUG
#pragma comment(linker,"/merge:.rdata=.data")
#pragma comment(linker,"/merge:.text=.data")
#pragma comment(linker,"/FILEALIGN:0x200")
#endif // _DEBUG
TCHAR szAppName[] = _T("delthis");
TCHAR szUsage[] = _T("Usage:\r\n\r\nselfdel [options]\r\n\r\nOptions:\r\n-u (Uninstall)\r\n-pid Pid\r\n-exe Path");
TCHAR szError1[] = _T("Failed to open process [%u]");
TCHAR szDeleting[] = _T("Deleting:\r\n\r\n%s");int _tatoi(TCHAR *num)
{
int n = 0;
TCHAR *nptr = num;
while(*nptr && IsCharAlphaNumeric(*nptr) && !IsCharAlpha(*nptr))
n = 10 * n + (*nptr++ - '0'); return n;
}void MyZeroMem(void *mem, DWORD bytes)
{
BYTE *bptr = (BYTE *)mem; while(bytes--)
*bptr++ = 0;
}//
// Delete THIS executable by spawning a copy off
//
void CommitSuicide(void)
{
HANDLE hTemp;
char szPath[MAX_PATH];
char szTemp[MAX_PATH];
char szBig [MAX_PATH*2 + 100]; STARTUPINFO si;
PROCESS_INFORMATION pi;
UINT ret; //
// Open a temporary file
//
GetTempPath(MAX_PATH, szTemp);
lstrcat(szTemp, "selfdel.exe"); //
// Get the current executable path
//
GetModuleFileName(0, szPath, MAX_PATH);
//
// Copy ourselves into the temporary file
//
CopyFile(szPath, szTemp, FALSE); //
// Open the temporary file, with DELETE_ON_CLOSE access.
// When we finally exit, the temporary file will get deleted
//
hTemp = CreateFile(szTemp, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, 0,
OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0); //
// Create a process using the temporary executable. This will cause
// the file's handle count to increase, so we can close it,
// without it deleting itself
//
MyZeroMem(&si, sizeof(STARTUPINFO));
MyZeroMem(&pi, sizeof(PROCESS_INFORMATION)); si.cb = sizeof(STARTUPINFO); wsprintf(szBig, "\"%s\" -pid %u -exe \"%s\"",
szTemp,
GetCurrentProcessId(),
szPath);
ret = CreateProcess(0, szBig, 0, 0, FALSE, NORMAL_PRIORITY_CLASS, 0, 0, &si, &pi); //Close our handle to the new process. Because the process is
//memory-mapped, there will still be a handle held by the O/S, so
//it won't get deleted. Give the other process a chance to run..
Sleep(100);
CloseHandle(hTemp);
}//
// Wait for the specified Process to terminate,
// then delete the exe's path
//
void DeleteExe(DWORD dwPid, TCHAR *szPath)
{
HANDLE hProcess;
TCHAR szErr[MAX_PATH+32]; //
// Open the process
//
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, dwPid); if(hProcess == 0)
{
wsprintf(szErr, szError1, dwPid);
MessageBox(0, szErr, szAppName, MB_OK|MB_ICONINFORMATION);
return;
} //
// Wait for process to die
//
WaitForSingleObject(hProcess, INFINITE);
CloseHandle(hProcess); //
// Delete the process
//
DeleteFile(szPath);
}TCHAR * GetNextArg(TCHAR *szPtr, TCHAR *szOut)
{
TCHAR *pOut = szOut;
TCHAR ch = *szPtr++; if(ch == '\0')
return 0; //Skip white-space
while(ch == ' ' || ch == '\t')
{
ch = *szPtr++;
} //Process quoted strings
if(ch == '\"')
{
ch = *szPtr++;
while(ch && ch != '\"')
{
*szOut++ = ch;
ch = *szPtr++; } *szOut = '\0';
return szPtr;
} //Return the next argument
while(ch && ch != ' ' && ch != '\t')
{
*szOut++ = ch;
ch = *szPtr++;
} *szOut = '\0';
return szPtr;
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd)
{
DWORD dwProcessId;
TCHAR *ptr;
TCHAR buf[MAX_PATH]; ptr = lpCmdLine; //
// Get options..
//
ptr = GetNextArg(ptr, buf); if(lstrcmpi(buf, "-u") == 0)
{
CommitSuicide();
ExitProcess(0);
return 0;
}
if(lstrcmpi(buf, "-pid") == 0)
{
//Pid specified - now get the PID
ptr = GetNextArg(ptr, buf); dwProcessId = _tatoi(buf); //get the next option
ptr = GetNextArg(ptr, buf); if(lstrcmpi(buf, "-exe") == 0)
{
//exe-path specified - get the path
ptr = GetNextArg(ptr, buf);
DeleteExe(dwProcessId, buf);
return 0;
}
else
{
return 1;
}
}
else
{
//return failure
return 1;
} return 0;
}//
// Usage:
// selfdel.exe [-u | -pid<PID> -exe<path>]
//
int WINAPI WinMainCRTStartup()
{
UINT ret;
TCHAR *pszCmdLine;
TCHAR temp[MAX_PATH]; HINSTANCE hInst = GetModuleHandle(0);
pszCmdLine = GetCommandLine(); pszCmdLine = GetNextArg(pszCmdLine, temp);
ret = WinMain(hInst, 0, pszCmdLine, SW_SHOWNORMAL);
if(ret != 0)
{
MessageBox(0, szUsage, szAppName, MB_OK|MB_ICONINFORMATION);
} ExitProcess(ret);
return 0;
}