【问题标题】:DELETE_ON_CLOSE occurring too earlyDELETE_ON_CLOSE 发生得太早
【发布时间】:2013-08-13 20:15:18
【问题描述】:

我正在尝试在另一台机器上创建一个进程,该进程完成后会自行删除。我将 DELETE_ON_CLOSE 标志与 CreateFile 一起使用。这种方法有点流行,但我遇到了麻烦,因为我无法在它打开时执行它(预期但这是一些解决方案所做的)。为了解决这个问题,我尝试使用读取权限打开文件。 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);

【问题讨论】:

  • 这是一条死胡同。使用existing answer
  • 我没有看到合适的现有答案。
  • 您说“我正在尝试在另一台机器上创建一个删除自身的进程”,但您的代码看起来只是想在关闭时删除一个远程文件——是什么?您是否正在尝试创建一个自删除的可执行文件?
  • 我希望我不必修改我发送过来的可执行文件的代码。我希望这里有一个通用的解决方案。将它添加到我们所有现有的项目中,包括未来的所有新项目,以及我什至无法控制的项目,这将是一件非常困难的事情。
  • 你确定HANDLE remote_retain_fh = CreateFile(&remote_file_location[0],... 真的成功了吗,因为在发布的来源中没有错误检查此调用的 dnoe。

标签: c++ winapi


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-21
    • 1970-01-01
    • 2022-01-12
    • 2012-05-17
    相关资源
    最近更新 更多