Supprimer plusieurs fichiers avec une seule invite Windows (FileSystem)


Ross Patterson

J'ai une application WPF qui affiche les fichiers dans un dossier. L'utilisateur peut sélectionner plusieurs fichiers et choisir de les supprimer, actuellement j'utilise cette logique avec utilise FileSystem de la bibliothèque VisualBasic.FileIO :

foreach (Item item in items)
{
     if (item.IsDirectory)
     {
          FileSystem.DeleteDirectory(item.FullPath, UIOption.AllDialogs, RecycleOption.SendToRecycleBin);
     }
     else
     {
          FileSystem.DeleteFile(item.FullPath, UIOption.AllDialogs, RecycleOption.SendToRecycleBin);
     }
} 

Le problème ici est que si les utilisateurs ont l'option Windows "Afficher la boîte de dialogue de confirmation de suppression" activée :entrez la description de l'image ici

Ils reçoivent une invite Windows pour chaque fichier.

Je veux qu'ils obtiennent une seule invite comme celle-ci :

entrez la description de l'image ici

Y a-t-il un moyen de faire cela?

Même si cela implique un PInvoke d'une fonction WinAPI ?

41686d6564

Avec PInvoke, nous pouvons utiliser SHFileOperation avec la fonction FO_DELETE pour envoyer des objets du système de fichiers à la corbeille. Selon la documentation, nous pouvons envoyer plusieurs chemins à la fois en les joignant avec un caractère NULL :

Bien que ce membre soit déclaré comme une seule chaîne terminée par un caractère nul, il s'agit en fait d'un tampon pouvant contenir plusieurs noms de fichiers délimités par des caractères nuls. Chaque nom de fichier se termine par un seul caractère NULL. Le dernier nom de fichier se termine par un double caractère NULL ("\0\0") pour indiquer la fin du tampon.

Au lieu de tout écrire à partir de zéro, utilisons des parties du code dans cette réponse et ajustons-le pour qu'il fonctionne avec plusieurs chemins. Nous aurons quelque chose comme ça :

public class FileOperationAPIWrapper
{
    /// <summary>
    /// Possible flags for the SHFileOperation method.
    /// </summary>
    [Flags]
    public enum FileOperationFlags : ushort
    {
        /// <summary>
        /// Do not show a dialog during the process
        /// </summary>
        FOF_SILENT = 0x0004,
        /// <summary>
        /// Do not ask the user to confirm selection
        /// </summary>
        FOF_NOCONFIRMATION = 0x0010,
        /// <summary>
        /// Delete the file to the recycle bin.  (Required flag to send a file to the bin
        /// </summary>
        FOF_ALLOWUNDO = 0x0040,
        /// <summary>
        /// Do not show the names of the files or folders that are being recycled.
        /// </summary>
        FOF_SIMPLEPROGRESS = 0x0100,
        /// <summary>
        /// Surpress errors, if any occur during the process.
        /// </summary>
        FOF_NOERRORUI = 0x0400,
        /// <summary>
        /// Warn if files are too big to fit in the recycle bin and will need
        /// to be deleted completely.
        /// </summary>
        FOF_WANTNUKEWARNING = 0x4000,
    }

    /// <summary>
    /// File Operation Function Type for SHFileOperation
    /// </summary>
    public enum FileOperationType : uint
    {
        /// <summary>
        /// Move the objects
        /// </summary>
        FO_MOVE = 0x0001,
        /// <summary>
        /// Copy the objects
        /// </summary>
        FO_COPY = 0x0002,
        /// <summary>
        /// Delete (or recycle) the objects
        /// </summary>
        FO_DELETE = 0x0003,
        /// <summary>
        /// Rename the object(s)
        /// </summary>
        FO_RENAME = 0x0004,
    }

    /// <summary>
    /// SHFILEOPSTRUCT for SHFileOperation from COM
    /// </summary>
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    private struct SHFILEOPSTRUCT
    {
        public IntPtr hwnd;
        [MarshalAs(UnmanagedType.U4)]
        public FileOperationType wFunc;
        public string pFrom;
        public string pTo;
        public FileOperationFlags fFlags;
        [MarshalAs(UnmanagedType.Bool)]
        public bool fAnyOperationsAborted;
        public IntPtr hNameMappings;
        public string lpszProgressTitle;
    }

    [DllImport("shell32.dll", CharSet = CharSet.Auto)]
    private static extern int SHFileOperation(ref SHFILEOPSTRUCT FileOp);

    public static bool SendToRecycleBin(string path, FileOperationFlags flags)
    {
        return SendToRecycleBin(new[] { path }, flags);
    }

    public static bool SendToRecycleBin(IList<string> paths, FileOperationFlags flags)
    {
        try
        {
            var fs = new SHFILEOPSTRUCT
            {
                wFunc = FileOperationType.FO_DELETE,
                pFrom = string.Join("\0", paths) + '\0' + '\0',
                fFlags = FileOperationFlags.FOF_ALLOWUNDO | flags
            };
            SHFileOperation(ref fs);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }
}

Usage:

FileOperationAPIWrapper.SendToRecycleBin(items,
    FileOperationAPIWrapper.FileOperationFlags.FOF_WANTNUKEWARNING);

Articles connexes


Supprimer plusieurs fichiers en une seule ligne PS

Ts Rhino Je me demandais s'il existe un moyen élégant de supprimer plusieurs fichiers dans un dictionnaire s'ils existent, avec PowerShell. Ma tentative actuelle ne fonctionne pas tout à fait. $var1,$var2,$var3,$var4,$var5,$var6,$var7,$var8,$var9,$var10,$var11

Envoi de plusieurs fichiers à un servlet avec une seule connexion

user549335: J'écris un client de bureau Java qui enverra plusieurs fichiers sur le fil à un servlet à l'aide d'une demande de publication. Dans le servlet, j'obtiens le flux d'entrée de la demande de réception des fichiers. Le servlet écrira les fichiers sur l

trouver plusieurs chemins de fichiers avec une seule chaîne

Daniel F. J'ai essayé d'écrire un script batch qui trouve tous les chemins de fichiers qui ont le même nom que la chaîne d'entrée. pour le moment, il ne peut trouver que le premier fichier trouvé, et je ne peux pas penser à un moyen de le faire répertorier plu

Plusieurs commandes rsync avec une seule invite de mot de passe

David S Afin de synchroniser deux répertoires source (par exemple ~ / src1 et ~ / src2) vers deux destinations distinctes (par exemple / tgt et / tgt / sub_tgt) dans le système distant en utilisant une seule commande rsync, je fais: rsync ~/src1 uid@host:/tgt;