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.EnumerateFilesこれをandを使用して 2 つのループで実行すると、フォルダ内のファイルの前にフォルダがリストされるため、削除は失敗しますDirectory.EnumerateDirectoriesDirectory.EnumerateFileSystemEntries

4

2 に答える 2

9

私が見たほとんどの実装では、ディレクトリ内のすべてのファイルが with で「削除」されMoveFileExMOVEFILE_DELAY_UNTIL_REBOOT次にディレクトリが同じ方法で「削除」されます。操作の順序は再起動時に保持されます。最初にファイルが削除され、次にディレクトリが削除されます。

于 2014-01-13T19:01:15.067 に答える
2

Michael Gunterの答えに同意します。マイケルが提案したことを行うコードの例を追加しました。

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 に答える