3

Users从域中删除用户后,我试图删除文件夹中的用户配置文件文件夹。问题是有时系统可能正在使用该文件夹。

问题是使用MOVEFILE_DELAY_UNTIL_REBOOTwithMoveFileEx只会删除空文件夹。

从 MSDN

如果dwFlags指定MOVEFILE_DELAY_UNTIL_REBOOT并且lpNewFileNameNULL,则 MoveFileEx 注册lpExistingFileName文件以在系统重新启动时删除。如果lpExistingFileName引用一个目录,则系统仅在目录为空时才会在重新启动时删除该目录。

删除其中包含正在使用的文件的非空文件夹的正确方法是什么?


这是一个基于 Michel 答案的简单测试程序,它按预期工作。

internal static class Program
{
    private static void Main(string[] args)
    {
        foreach (var file in Directory.EnumerateFiles(args[0], "*", SearchOption.AllDirectories))
        {
            Console.WriteLine(file);
        }

        foreach (var directory in Directory.EnumerateDirectories(args[0], "*", SearchOption.AllDirectories))
        {
            Console.WriteLine(directory);
            DeleteFileOnReboot(directory);
        }

        DeleteFileOnReboot(args[0]);
    }

    private static void DeleteFileOnReboot(string file)
    {
        bool result = MoveFileEx(file, null, MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT);
        try
        {
            if (!result)
                throw new Win32Exception();
        }
        catch (Win32Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, MoveFileFlags dwFlags);

}

[Flags]
enum MoveFileFlags
{
    MOVEFILE_REPLACE_EXISTING = 0x00000001,
    MOVEFILE_COPY_ALLOWED = 0x00000002,
    MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004,
    MOVEFILE_WRITE_THROUGH = 0x00000008,
    MOVEFILE_CREATE_HARDLINK = 0x00000010,
    MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x00000020
}

我在两个循环中执行此操作Directory.EnumerateFilesDirectory.EnumerateDirectories因为Directory.EnumerateFileSystemEntries将在文件夹中的文件之前列出文件夹,因此删除将失败。

4

2 回答 2

9

在我见过的大多数实现中,目录中的每个文件都用MoveFileExwith “删除” MOVEFILE_DELAY_UNTIL_REBOOT,然后以同样的方式“删除”目录。重新启动时会保留操作顺序——首先删除文件,然后删除目录。

于 2014-01-13T19:01:15.067 回答
2

我同意迈克尔冈特的回答。刚刚添加了迈克尔建议的代码示例。

public class Cleanuper
{
    private void PendingDeleteDirectory(string directoryPath)
    {
        foreach (string directory in Directory.GetDirectories(directoryPath, "*", SearchOption.TopDirectoryOnly))
        {
            PendingDeleteDirectory(directory);
        }

        foreach (string file in Directory.GetFiles(directoryPath, "*", SearchOption.TopDirectoryOnly))
        {
            NativeMethods.MoveFileEx(file, null, MoveFileFlags.DelayUntilReboot);
        }
        NativeMethods.MoveFileEx(directoryPath, null, MoveFileFlags.DelayUntilReboot);
    }
}

public static class NativeMethods
{
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    internal static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, MoveFileFlags dwFlags);
}

[Flags]
public enum MoveFileFlags
{
    DelayUntilReboot = 0x00000004
}
于 2017-05-16T22:54:55.213 回答