2010-02-26 10 views
3

J'ai cette classe qui semble fonctionner assez bien sur les non-64 bits.Suppression d'un fichier dans la corbeille sous Windows x64 en C#

using System; 
using System.Runtime.InteropServices; 

namespace DeleteToRecycleBin 
{ 
/// <summary> 
/// Send files directly to the recycle bin. 
/// </summary> 
public class RecybleBin 
{ 

    /// <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, Pack = 1)] 
    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 readonly bool fAnyOperationsAborted; 
     public readonly IntPtr hNameMappings; 
     public readonly string lpszProgressTitle; 
    } 

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

    /// <summary> 
    /// Send file to recycle bin 
    /// </summary> 
    /// <param name="path">Location of directory or file to recycle</param> 
    /// <param name="flags">FileOperationFlags to add in addition to FOF_ALLOWUNDO</param> 
    public static bool Send(string path, FileOperationFlags flags) 
    { 
     try 
     { 
      SHFILEOPSTRUCT fs = new SHFILEOPSTRUCT 
            { 
             wFunc = FileOperationType.FO_DELETE, 
             pFrom = path + '\0' + '\0', 
             fFlags = FileOperationFlags.FOF_ALLOWUNDO | flags 
            }; 

      // important to double-terminate the string. 
      SHFileOperation(ref fs); 
      return true; 
     } 
     catch (Exception) 
     { 
      return false; 
     } 
    } 

    /// <summary> 
    /// Send file to recycle bin. Display dialog, display warning if files are too big to fit (FOF_WANTNUKEWARNING) 
    /// </summary> 
    /// <param name="path">Location of directory or file to recycle</param> 
    public static bool Send(string path) { 
     return Send(path, FileOperationFlags.FOF_NOCONFIRMATION | FileOperationFlags.FOF_WANTNUKEWARNING); 
    } 

    /// <summary> 
    /// Send file silently to recycle bin. Surpress dialog, surpress errors, delete if too large. 
    /// </summary> 
    /// <param name="path">Location of directory or file to recycle</param> 
    public static bool SendSilent(string path) 
    { 
     return Send(path, FileOperationFlags.FOF_NOCONFIRMATION | FileOperationFlags.FOF_NOERRORUI | FileOperationFlags.FOF_SILENT); 

    } 
} 

}

De toute façon de le réparer si cela fonctionne bien sur x64 aussi? J'ai essayé de chanter ushort à ulong et quelques autres modifications, mais cela ne fonctionne pas.

Je sais qu'il existe d'autres solutions qui nécessitent une référence à Microsoft.VisualBasic mais je préférerais p/invoke way.

CORRECT RÉPONSE EST:

Sous x64, le SHFILEOPSTRUCT doit être déclarée sans le paramètre pack = 1, ou il échouera. C'est vraiment pénible si vous voulez que votre code soit indépendant de la plateforme, car vous devez déclarer deux structures séparées, une avec Pack = 1 et une sans. Vous devez ensuite déclarer deux appels SHFileOperation différents, un pour chacune des structures. Ensuite, vous devez décider lequel appeler en fonction de si vous exécutez sur 32 ou 64 bits.

Répondre

2

Avez-vous regardé le site PInvoke? Il a une légère définition différente pour le type FILEOPSTRUCT, forçant Unicode pour une chose. Je me demande si le charset = auto est déroutant les choses ... comme il est par défaut à ANSI sur 32 bits, mais Unicode sur 64 bits et quelque chose ne va pas quelque part au milieu.

EDIT; En outre, l'approche de référence Visual Basic est simple ... Je sais que les gens ont une aversion pour une raison quelconque, mais les DLL pertinentes font toujours partie du framework de base, donc vous n'ajouterez pas de nouvelles dépendances.

+0

Le problème réside dans [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]. Pour 64bit, vous devez supprimer Pack = 1 et cela fonctionne !!! Depuis que vous m'avez indiqué le site PInvoke, il l'indique même là (juste en bas de l'article en disant d'enlever Pack = 1 quand il est en 64bit!) – MadBoy

+0

Ha ha, je n'ai même pas fait défiler jusque là, j'ai juste vu les différences Dans la définition de la structure principale, il semble que la solution soit un peu maladroite: –

+0

J'utilise 64 bits Windows 7 avec Pack = 1 pour FILEOPSTRUCT et ça marche avec moi sans aucun problème: | – TheBlueSky

6

Aussi étrange que cela puisse paraître, .NET a déjà des fonctions à supprimer dans la Corbeille ... mais elles sont dans l'espace de noms Microsoft.VisualBasic. Plus précisément, Microsoft.VisualBasic.FileIO.

using Microsoft.VisualBasic.FileIO; 

// class declaration, method start here 

// Send file to recycle bin without dialog 
FileSystem.DeleteFile("pathToFile", UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin); 

// Send file to recycle bin without dialog 
FileSystem.DeleteFile("pathToFile", UIOption.AllDialogs, RecycleOption.SendToRecycleBin); 

// Directories are the same, but with DeleteDirectory instead 
+0

bizarre en effet ... – RvdK

+0

Je connais cette solution mais préférerais celle sans utiliser de référence à VisualBasic. – MadBoy

+0

@MadBoy Pourquoi voulez-vous éviter de référencer Microsoft.VisualBasic? – Nick