2014-01-13 63 views
2

我從域中刪除用戶後,試圖刪除Users文件夾中的用戶配置文件文件夾。問題是該系統可能正在使用該文件夾的某些時間。重新啓動時刪除非空文件夾

問題是使用MOVEFILE_DELAY_UNTIL_REBOOTMoveFileEx只會刪除空的文件夾。

From the MSDN

如果dwFlags中指定MOVEFILE_DELAY_UNTIL_REBOOTlpNewFileNameNULL,MoveFileEx註冊lpExistingFileName文件系統重新啓動時被刪除。如果lpExistingFileName引用一個目錄,則只有在目錄爲空時,系統纔會在重新啓動時刪除該目錄。

什麼是正確的方式來刪除一個文件裏面有一個正在使用的非空文件夾?


這是基於米歇爾的回答一個簡單的測試程序,它按預期工作。

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將列出文件夾中的文件之前的文件夾,以便刪除將失敗。

回答

5

在我看到的大多數實現中,目錄中的每個文件都被「刪除」,MoveFileExMOVEFILE_DELAY_UNTIL_REBOOT,然後該目錄以同樣的方式「刪除」。操作順序在重新啓動時保留 - 文件首先被刪除,然後是目錄。

+0

這是代碼示例: –

0

我同意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 
}