背景
以前写过一个备份替换工具,功能是用新编译的dll替换老的,达到软件升级的目的,同时备份下老的dll防止发生意外;使用中有一个不方便的点,如果软件正在使用的时候是无法替换成功的,最近终于在这篇文章中找到了优化方案 :“替换运行中的文件”
代码
for (size_t t = 0; t < 5; t++)
{
if (MoveFileEx(sBackUpFileDir, sBackUpFileToDir, MOVEFILE_REPLACE_EXISTING) == 0)
{
if (t >= 5)
{
CString sText;
sText.Format("%d × Err !!!文件替换失敗:", i);
}
else
{
Sleep(10);
}
}
我使用了一个循环来调用这个接口,多调用几次可以避免某些情况下仍然替换失败的问题;
MoveFileEx是MoveFile函数的扩展函数,也是用来移动文件,不过多加了一些功能。MoveFileEx函数的原型如下:
BOOL MoveFileEx (
LPCTSTR lpExistingFileName, //要移动的文件名
LPCTSTR lpNewFileName, //移动后的文件名
DWORD dwFlags //移动的方式
);
其中
winbase.h:
- #define MOVEFILE_REPLACE_EXISTING 0x00000001
如果目标位置已存在同名文件,则该函数会替换该文件,而不会询问用户或抛出错误。这是默认行为 - #define MOVEFILE_COPY_ALLOWED 0x00000002
当尝试移动一个文件到不同的卷(即不同的驱动器或分区)时,通常操作会失败,因为 MoveFileEx 实际上尝试的是重命名操作,这在跨卷时是不允许的。设置此标志允许函数在遇到这种情况时,改为复制文件并删除原始文件,从而模拟移动操作。注意,这可能会导致数据不一致(如果在复制过程中原始文件被修改),并且可能不适用于所有情况。 - #define MOVEFILE_DELAY_UNTIL_REBOOT 0x00000004
当设置此标志时,MoveFileEx 不会在调用时立即移动文件。相反,它会在下一次系统重启时安排文件的移动。这对于在运行时无法移动或删除的文件(如某些系统文件或正在使用的文件)特别有用。在重启过程中,系统会在较早的启动阶段(在大多数服务和应用程序启动之前)尝试移动文件。 - #define MOVEFILE_WRITE_THROUGH 0x00000008
此标志的行为在不同版本的 Windows 中可能有所不同,但基本上,它旨在确保写入操作直接到达磁盘,而不会被缓存。这对于需要确保数据立即写入磁盘(例如,在涉及重要数据的操作中)的应用程序来说可能是有用的。然而,请注意,频繁使用此标志可能会影响性能,因为它绕过了操作系统的缓存机制。
文章中作者用if(MoveFileEx(cTempFileName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT) ;把目标文件位置设置为NULL来实现在重启后删除文件的操作也很有意思,在利用MoveFileEx实现程序的隐藏、自启动与自删除里面提到了这个方法可以用来删除比较顽固的文件;
当dwFlags参数被设置为MOVEFILE_DELAY_UNTIL_REBOOT时,MoveFileEx把重启后移动的文件和要移到的文件的位置 存在下面的多字符注册表值(REG_MULTI_SZ)里:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet \Control\Session\Manager\PendingFileRenameOperations。
参考资料
替换运行中的文件https://blog.csdn.net/xcntime/article/details/7371817
利用MoveFileEx实现程序的隐藏、自启动与自删除https://www.cnblogs.com/tt_mc/archive/2010/01/24/1655176.html