6

How would I go about marking one folder for deletion when the system reboots, using C#.

Thanks,

Dan Herbert
  • 99,428
  • 48
  • 189
  • 219

4 Answers4

18

Originally from:

http://abhi.dcmembers.com/blog/2009/03/24/mark-file-for-deletion-on-reboot/

Documentation:

https://learn.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-movefileexa#parameters

///
/// Consts defined in WINBASE.H
///
[Flags]
internal enum MoveFileFlags
{
    MOVEFILE_REPLACE_EXISTING = 1,
    MOVEFILE_COPY_ALLOWED = 2,
    MOVEFILE_DELAY_UNTIL_REBOOT = 4, //This value can be used only if the process is in the context of a user who belongs to the administrators group or the LocalSystem account
    MOVEFILE_WRITE_THROUGH  = 8
}


/// <summary>
/// Marks the file for deletion during next system reboot
/// </summary>
/// <param name="lpExistingFileName">The current name of the file or directory on the local computer.</param>
/// <param name="lpNewFileName">The new name of the file or directory on the local computer.</param>
/// <param name="dwFlags">MoveFileFlags</param>
/// <returns>bool</returns>
/// <remarks>http://msdn.microsoft.com/en-us/library/aa365240(VS.85).aspx</remarks>
[System.Runtime.InteropServices.DllImportAttribute("kernel32.dll",EntryPoint="MoveFileEx")]
internal static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName,
MoveFileFlags dwFlags);

//Usage for marking the file to delete on reboot
MoveFileEx(fileToDelete, null, MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT);
Hath
  • 12,606
  • 7
  • 36
  • 38
  • 2
    To compliment an otherwise fine answer, `[Flags]` is missing on `MoveFileFlags`. +1 –  Dec 14 '15 at 03:53
  • The problem is using MOVEFILE_DELAY_UNTIL_REBOOT with MoveFileEx will only delete folders that are empty. http://msdn.microsoft.com/en-us/library/windows/desktop/aa365240%28v=vs.85%29.aspx. So you need to to delete and set for deleting all files and subfolders inside the folder and only then delete folder. – Ainullin Damir May 16 '17 at 21:43
  • 1
    [The documentation states](https://learn.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-movefileexa#parameters) for the `MOVEFILE_DELAY_UNTIL_REBOOT` parameter: "_…This value can be used only if the process is in the context of a user who belongs to the administrators group or the LocalSystem account…_". – Uwe Keim Jan 22 '19 at 14:34
3

Use PInvoke and call MoveFileEx, passing null in as the destination....

This link has some sample code:

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

public const int MOVEFILE_DELAY_UNTIL_REBOOT = 0x4;

MoveFileEx(filename, null, MOVEFILE_DELAY_UNTIL_REBOOT);
John Weldon
  • 39,849
  • 11
  • 94
  • 127
1

quoted from http://abhi.dcmembers.com/blog/2009/03/24/mark-file-for-deletion-on-reboot/ :

///
/// Consts defined in WINBASE.H
///
internal enum MoveFileFlags
{
    MOVEFILE_REPLACE_EXISTING = 1,
    MOVEFILE_COPY_ALLOWED = 2,
    MOVEFILE_DELAY_UNTIL_REBOOT = 4,
    MOVEFILE_WRITE_THROUGH  = 8
}


/// <summary>
/// Marks the file for deletion during next system reboot
/// </summary>
/// <param name="lpExistingFileName">The current name of the file or directory on the     local computer.</param>
/// <param name="lpNewFileName">The new name of the file or directory on the local   computer.</param>
/// <param name="dwFlags">MoveFileFlags</param>
/// <returns>bool</returns>
/// <remarks>http://msdn.microsoft.com/en-us/library/aa365240(VS.85).aspx</remarks>
[System.Runtime.InteropServices.DllImportAttribute("kernel32.dll",EntryPoint="MoveFileEx")]
internal static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName,
MoveFileFlags dwFlags);

//Usage for marking the file to delete on reboot
MoveFileEx(fileToDelete, null, MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT);

edit:beaten

Miki Watts
  • 1,746
  • 1
  • 17
  • 27
1

The problem is using MOVEFILE_DELAY_UNTIL_REBOOT with MoveFileEx will only delete folders that are empty. Reference to documentation.

My solution is the following: every file in the directory is "deleted" with MoveFileEx with MOVEFILE_DELAY_UNTIL_REBOOT, and then the directory is "deleted" the same way.

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
}
Ainullin Damir
  • 305
  • 6
  • 17