DELETE_ON_CLOSE发生得太早了

时间:2013-08-13 20:15:18

标签: c++ winapi

我正在尝试在另一台机器上创建一个进程,该进程在完成后会自行删除。我正在使用带有CreateFile的DELETE_ON_CLOSE标志。这种方法有点受欢迎,但我遇到了麻烦,因为我无法在打开时执行它(预期但这就是某些解决方案所做的)。为了解决这个问题,我尝试使用读取权限打开文件。 DELETE_ON_CLOSE标志表示它应该只在所有指向它的指针都删除时删除它。我有一个指向它的指针,我关闭写句柄,文件删除使我的打开句柄不可读。任何其他方式都会很高兴。

我也考虑过这样一种可能性,因为这是一个远程文件系统,手柄上有一些时髦的东西。

我无法修改我发送的可执行代码,因此自我删除的可执行文件是我想要做的最后一件事。

让我的程序等待清理服务将导致它挂起不可接受的长时间,因为可能需要多长时间来销毁远程盒上的服务。

//Open remote file for reading and set the delete flag
HANDLE remote_fh = CreateFile(&remote_file_location[0], 
    GENERIC_WRITE, 
    FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 
    NULL, 
    CREATE_ALWAYS, 
    FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, 
    NULL);

if(!remote_fh)
{
    debug.DebugMessage(Error::GetErrorMessageW(GetLastError()));
    RevertToSelf();
    return dead_return;
}

//File to read from
HANDLE local_fh = CreateFile(&local_file_location[0],
    GENERIC_READ,
    FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL);


if(!local_fh)
{

    debug.DebugMessage(Error::GetErrorMessageW(GetLastError()));
    RevertToSelf();
    return dead_return;
}

byte buf[256];

DWORD bytesRead;
DWORD bytesWritten;

//Copy the file
while(ReadFile(local_fh, buf, 256, &bytesRead, NULL) && bytesRead > 0)
{
    WriteFile(remote_fh, buf, bytesRead, &bytesWritten, NULL);
}

CloseHandle(local_fh);


//Create a file retainer to hold the pointer so the file doesn't get deleted before the service starts
HANDLE remote_retain_fh = CreateFile(&remote_file_location[0],
    GENERIC_READ,
    FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL);

if (!remote_retain_fh)
{
    debug.DebugMessage(Error::GetErrorMessageW(GetLastError()));
    RevertToSelf();
    return dead_return;
}


CloseHandle(remote_fh);


//if(!CopyFile(&local_file_location[0], &remote_file_location[0], false))
//{
//  debug.DebugMessage(Error::GetErrorMessageW(GetLastError()));
//  RevertToSelf();
//  return dead_return;
//}

remote_service.Create(Service::GetServiceName().c_str());

//In the words of my daughter: "OH, OH, FILE ALL GONE!"
Pipe pipe(L"\\\\" + *hostname + L"\\pipe\\dbg");

CloseHandle(remote_fh);

1 个答案:

答案 0 :(得分:0)

FILE_FLAG_DELETE_ON_CLOSE需要FILE_SHARE_DELETE权限。问题在于,当进程启动时,操作系统会打开可执行文件的文件句柄,并且不需要共享FILE_SHARE_DELETE权限,这样在进程打开时就无法删除可执行文件。

考虑:你打开一个可执行文件的句柄而没有独占的FILE_SHARE_DELETE,但只说FILE_GENERIC_READ。其他人(您,后来,或者确实是另一个线程或进程)然后启动该可执行文件。没问题,因为没有人试图删除可执行文件。但是如果您当时尝试获得FILE_SHARE_DELETE权限,那么您将失败,因为可执行文件已经以独占文件删除权限运行。