How to synchronously and sequentially delete a folder on NTFS using C #

Directory.Delete(dir, true);

not synchronous.

On a straight line, you can still manipulate / read the directory.

For example, this:

Directory.Delete(destinationDir, true);
Directory.CreateDirectory(destinationDir);
Thread.Sleep(1000);

causes the folder to not exist. The deletion is performed by async, is CreateDirectorynot created because it already exists, and then deletes the actual lights and deletes the directory.

Is there an IO API that will give me consistency?

A response involving Thread.Sleepwill call Zalgo. I want to find a real solution.

+4
source share
3 answers

++ , Windows / . -, .NET, , , Directory.CreateDirectory(), , Directory.Delete().

, Win32:

printf("Press enter to begin...");
while(getchar() != '\n');

LPCSTR DeletePath = "C:\\test\\DeleteMe"; //The directory to delete.
_SHFILEOPSTRUCTA* fileopt = new _SHFILEOPSTRUCTA();

fileopt->hwnd = NULL;        //No window handle.
fileopt->wFunc = FO_DELETE;  //Delete mode.
fileopt->pFrom = DeletePath; //The directory to delete.
fileopt->pTo = NULL;         //No target directory (this is only used when moving, copying, etc.).
fileopt->fFlags = FOF_NO_UI; //Display no UI dialogs.

int Success = SHFileOperationA(fileopt); //Remove the entire directory and all it contents.
bool Success2 = CreateDirectoryA(DeletePath, NULL); //Create a new directory.

LPCSTR ReturnedValue = "False"; //I'm no C++ guru, so please don't hate. :)
LPCSTR ReturnedValue2 = "False";
if(Success == 0) { ReturnedValue = "True"; } //The SHFileOperation() returns 0 if it succeeds.
if(Success2 == true) { ReturnedValue2 = "True"; }

//Print the result of SHFileOperation().
printf("Returned value: ");
printf(ReturnedValue);
printf("\n");

//Print the result of CreateDirectory().
printf("Returned value 2: ");
printf(ReturnedValue2);
printf("\n");

//Continue.
printf("Press enter to exit...");
while(getchar() != '\n');

ENTER , , , - , .

, , , , , SHFileOperation(), , Directory.Delete() .NET- (. ).


--- EDIT ---

# ! , ( ) P/Invoked SHFileOperation(), 2, ERROR_FILE_NOT_FOUND. , 0 ().

NativeMethods.cs:

:

using System;
using System.Runtime.InteropServices;

:

[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
public static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHFILEOPSTRUCT
{
    public IntPtr hwnd;
    public FileFuncFlags wFunc;

    [MarshalAs(UnmanagedType.LPWStr)]
    public string pFrom;

    [MarshalAs(UnmanagedType.LPWStr)]
    public string pTo;
    public FILEOP_FLAGS fFlags;

    [MarshalAs(UnmanagedType.Bool)]
    public bool fAnyOperationsAborted;
    public IntPtr hNameMappings;

    [MarshalAs(UnmanagedType.LPWStr)]
    public string lpszProgressTitle;
}

public enum FileFuncFlags : uint
{
    FO_MOVE = 0x1,
    FO_COPY = 0x2,
    FO_DELETE = 0x3,
    FO_RENAME = 0x4
}

[Flags]
public enum FILEOP_FLAGS : ushort
{
    FOF_MULTIDESTFILES = 0x1,
    FOF_CONFIRMMOUSE = 0x2,
    /// <summary>
    /// Don't create progress/report
    /// </summary>
    FOF_SILENT = 0x4,
    FOF_RENAMEONCOLLISION = 0x8,
    /// <summary>
    /// Don't prompt the user.
    /// </summary>
    FOF_NOCONFIRMATION = 0x10,
    /// <summary>
    /// Fill in SHFILEOPSTRUCT.hNameMappings.
    /// Must be freed using SHFreeNameMappings
    /// </summary>
    FOF_WANTMAPPINGHANDLE = 0x20,
    FOF_ALLOWUNDO = 0x40,
    /// <summary>
    /// On *.*, do only files
    /// </summary>
    FOF_FILESONLY = 0x80,
    /// <summary>
    /// Don't show names of files
    /// </summary>
    FOF_SIMPLEPROGRESS = 0x100,
    /// <summary>
    /// Don't confirm making any needed dirs
    /// </summary>
    FOF_NOCONFIRMMKDIR = 0x200,
    /// <summary>
    /// Don't put up error UI
    /// </summary>
    FOF_NOERRORUI = 0x400,
    /// <summary>
    /// Dont copy NT file Security Attributes
    /// </summary>
    FOF_NOCOPYSECURITYATTRIBS = 0x800,
    /// <summary>
    /// Don't recurse into directories.
    /// </summary>
    FOF_NORECURSION = 0x1000,
    /// <summary>
    /// Don't operate on connected elements.
    /// </summary>
    FOF_NO_CONNECTED_ELEMENTS = 0x2000,
    /// <summary>
    /// During delete operation, 
    /// warn if nuking instead of recycling (partially overrides FOF_NOCONFIRMATION)
    /// </summary>
    FOF_WANTNUKEWARNING = 0x4000,
    /// <summary>
    /// Treat reparse points as objects, not containers
    /// </summary>
    FOF_NORECURSEREPARSE = 0x8000
}

:

string DeletePath = "C:\\test\\DeleteMe";
NativeMethods.SHFILEOPSTRUCT fileopt = new NativeMethods.SHFILEOPSTRUCT();

fileopt.hwnd = IntPtr.Zero;
fileopt.wFunc = NativeMethods.FileFuncFlags.FO_DELETE;
fileopt.pFrom = DeletePath;
fileopt.pTo = null;
fileopt.fFlags = NativeMethods.FILEOP_FLAGS.FOF_SILENT | NativeMethods.FILEOP_FLAGS.FOF_NOCONFIRMATION |
                 NativeMethods.FILEOP_FLAGS.FOF_NOERRORUI | NativeMethods.FILEOP_FLAGS.FOF_NOCONFIRMMKDIR; //Equivalent of FOF_NO_UI.

int Success = NativeMethods.SHFileOperation(ref fileopt);
Directory.CreateDirectory(DeletePath);

MessageBox.Show("Operation returned value: " + Success.ToString(), "Test", MessageBoxButtons.OK, MessageBoxIcon.Information);

, !

+1

- , / .

FileWatcher , .

+1

, , .net Framework . PowerShell , .Net , - :

Remove-Item -Recurse -Force "C:\tempfolder"
New-Item -ItemType Directory "C:\tempfolder"

( ) , :

var path = @"C:\tempfolder";
var watcher = new FileSystemWatcher(path);
watcher.Deleted += (sender, args) => Directory.CreateDirectory(args.FullPath);
Directory.Delete(path, true);

, , , , ++ API .

0

All Articles