Windows API MoveFile()无法运行exe

Arx*_*rxz 1 c windows winapi

这是一个简单的C程序,用于说明:

#include <windows.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    //MoveFile(argv[0], "dst.exe");
    getchar();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

从上面的代码制作一个test.exe.

现在执行test.exe,由于getchar(),test.exe挂起,然后我可以自由剪切和粘贴这个exe.

但是,当我取消注释时MoveFile(argv[0], "dst.exe");,我希望它可以移动到dst.exe,结果是有一个dst.exe,而program.exe仍然存在,就像CopyFile()那样.

据我所知,在Windows中,当exe运行时,我可以重命名它,移动它,但不能删除它,它MoveFile()表现为组合CopyFile()DeleteFile()

并且还可以从Microsoft doc MoveFileEx中看到这一点.

BOOL WINAPI MoveFileEx(
  _In_     LPCTSTR lpExistingFileName,
  _In_opt_ LPCTSTR lpNewFileName,
  _In_     DWORD   dwFlags
);
Run Code Online (Sandbox Code Playgroud)

dwFlags有一个选项 MOVEFILE_COPY_ALLOWED

该文件将被移动到另一个卷,该函数使用CopyFile和DeleteFile函数模拟移动.如果文件已成功复制到其他卷并且无法删除原始文件,则该函数将成功保留源文件.该值不能与MOVEFILE_DELAY_UNTIL_REBOOT一起使用.

进一步确认我的猜测,我MoveFileEx()用选项测试MOVEFILE_REPLACE_EXISTING,重新编译程序,运行它,现在MoveFileEx()只是失败返回,甚至没有生成dst.exe.

但我肯定可以在运行时剪切和粘贴该exe,MoveFileEx()应该这样做,为什么???

如果他们不能,我该怎么做就像剪切和粘贴一样.

fre*_*eim 5

如果目标目标位于同一卷上,则MoveFile只会更新相应的目录条目.文件的MFT记录未更改,其索引保持不变,其内容未被触及.因为文件根本不受影响,所以即使文件正在使用,你也可以在相同的目录(即重命名)或相同的卷内移动它(注意:这对于正在执行的文件是正确的;通常,这是真的仅当文件使用FILE_SHARE_DELETE打开时).

如果目标目录位于另一个卷上,则系统需要复制它(如果文件以独占模式打开将失败)并在旧卷上删除它(如果文件正在使用,将无条件地失败).

剪切和粘贴在相同的卷内正常工作,而不是在不同的卷上.原因是文件剪贴板操作使用与文本操作不同的技术.

当您选择文本并按Ctrl-X时,文本字符串将移动到已分配的全局内存块,并将该块传递给Windows.该程序不再拥有它.该文本实际上位于Windows剪贴板中,您可以根据需要多次粘贴它.

当您在文件上按Ctrl-X时,它不会移动到剪贴板.剪贴板将接收文件描述符,其中包含有关文件和请求的操作的信息(此技术称为延迟呈现).当您按Ctrl-C时,剪贴板将只是要求对象所有者(即Windows资源管理器)执行所请求的操作.Explorer将使用完全相同的MoveFile执行它.

请注意,您只能粘贴一个剪切文件,因为第一个Ctrl-C将使剪贴板中的描述符无效.复制的文件可以粘贴多次.