2009-10-18 5 views
12

Dato una cartella, come posso dire che si tratta di un cestino? Ho trovato un answer per C++ ma non per C#.Come posso dire che una directory è il cestino in C#?

La mia prima idea era di verificare FileAttributes.System (che sarebbe un'approssimazione accettabile nel mio caso) ma in realtà quel flag è cancellato nella cartella di riciclo.

Le soluzioni grezze che utilizzano i nomi delle cartelle codificati sono fuori questione (siamo nel 2009 dopo tutto).

+4

Non puoi semplicemente adattare la soluzione C++ a C#? Se lo pubblichi qui puoi ottenere aiuto anche in questo. Chiamare le funzioni API da C# è certamente possibile e non magico. – Joey

+0

È la prima domanda nella casella Correlati;) Aggiungerò comunque un collegamento diretto. – mafu

+0

Ovviamente, preferirei fortemente una soluzione integrata in .NET, se possibile. – mafu

risposta

7

C'è un piccolo problema qui. Il Cestino di Windows è una cartella virtuale e in realtà non esiste. I file che vedi non sono effettivamente in quella cartella, sono la rappresentazione di file esistenti su disco che sono stati rinominati con un nome speciale, che li "rimuove" dal file system visibile, ma non da quello fisico.

È possibile "provarlo" da soli chiedendo la posizione della cartella utilizzando l'API win32. Si tornerà E_FAIL per il Cestino, ma non per altre cartelle (vedi SHGetKnownFolderPath on pinvoke.net (and on MSDN) per tutte le costanti che è possibile utilizzare e le dichiarazioni necessarie per questo codice per eseguire):

IntPtr ptrRecycleBinPath; 
// try it with KnownFolder.QuickLaunch to see it working: 
HRESULT hr = (HRESULT) SHGetKnownFolderPath(
    KnownFolder.RecycleBinFolder, 
    0, 
    IntPtr.Zero, 
    out ptrRecycleBinPath); 

if (hr == HRESULT.E_FAIL) 
{ 
    Console.WriteLine("No folder avaialable, virtual folder"); 
} 
else if (hr == HRESULT.S_OK) 
{ 
    string RecycleBinPath = Marshal.PtrToStringUni(ptrRecycleBinPath); 
    Marshal.FreeCoTaskMem(ptrRecycleBinPath); 
    Console.WriteLine("path: " + RecycleBinPath); 
} 

// for convenience, you can use the code above 
// directly if you paste the follow declarations in your class: 

// get a "known path" 
[DllImport("shell32.dll")] 
static extern long SHGetKnownFolderPath(
    [MarshalAs(UnmanagedType.LPStruct)] Guid rfid, 
    uint dwFlags, 
    IntPtr hToken, 
    out IntPtr pszPath); 

// known folder GUID declarations 
public static class KnownFolder 
{ 
    // many more entries exist, left out for clarity here 

    public static readonly Guid RecycleBinFolder = 
     new Guid("B7534046-3ECB-4C18-BE4E-64CD4CB7D6AC"); 

    public static readonly Guid QuickLaunch = 
     new Guid("52a4f021-7b75-48a9-9f6b-4b87a210bc8f"); 

    //.... 
} 

// results of COM invocations: 
enum HRESULT : uint 
{ 
    S_FALSE = 0x0001, 
    S_OK = 0x0000, 
    E_FAIL = 0x80004005, 
    E_INVALIDARG = 0x80070057, 
    E_OUTOFMEMORY = 0x8007000E 
} 

Il FolderName falso "$ Recycle.bin " viene ripetuto per ogni unità. Il nome nascosto non è memorizzato nel registro e non è accessibile dall'API in quanto tale. Il precedente suggerito KnownFolderHelper non recupererà queste informazioni (la stessa lib ha un metodo con nome per ottenere il Cestino, ha anche un GetPath, si presenterà vuoto).

Ma non tutto è perduto. Questo "nome file" o "nome cartella" falso non esistente contiene un file nascosto simile a "S-1-5-21-2703390745-3900912742-210389625-1000" (il tuo sarà diverso).È uno dei due modi "affidabili" per scoprire se un determinato nome di file è effettivamente una directory virtuale del cestino (in alternativa: eliminare un file tramite SHFileOperation, explained here e verificare se compare nella cartella in cui si trova):

Nota: non so quali siano le cartelle nascoste su altre versioni di Win32, è necessario sperimentare un po '. Hanno tutti il ​​sistema e il flag nascosto e sembrano un GUID distrutto.

I documenti API non sono molto chiari al riguardo, ma se hai bisogno di conferma, this page explains che non c'è davvero alcun percorso che può essere recuperato (lo older CSIDL related page è molto meno chiaro su di esso).

Aggiornamento: approcci alternativi con SHGetSpecialFolderPath, SHGetSpecialFolderLocation, ShellAPI.SHGetFolderLocation e SHGetPathFromIDList tutte falliscono con la stessa: o un risultato vuoto o un errore. Ho testato tutte le funzioni sia per il Cestino che per AppData (per essere sicuro di aver usato i parametri corretti).

Solo la documentazione su ShGetPathFromIDListEx ha detto esplicitamente, citazione: "Tranne i nomi di stampante UNC, se la posizione specificata dal parametro pidl non fa parte del file system, questa funzione non riesce.".

2

La maggior parte dei metodi correlati al cestino sono stati scritti in C++ come indicato. Si potrebbe creare una classe wrapper nell'applicazione utilizzando il managed extensions to C++, allora si dovrà utilizzare DllImport come questo:

using System; 
using System.Runtime.InteropServices; 

class MainApp 
{ 
[DllImport("user32.dll", EntryPoint="MessageBox")] 
public static extern int MessageBox(int hWnd, String strMessage, String 
strCaption, uint uiType); 

public static void Main() 
{ 
MessageBox(0, "Hello, this is PInvoke in operation!", ".NET", 0); 
} 
} 

Ci sono anche articoli là fuori che fanno questo in qualche altro modo con C#, la maggior parte di loro usano PInvoke o fare affidamento sulla cartella con $ Recycle nel suo nome. Di seguito sono riportati alcuni link che ho trovato per questo argomento

http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/05f1476f-a101-4766-847b-0bdf4f6ad397

http://www.codeproject.com/KB/shell/recyclebin.aspx

http://www.pinvoke.net/default.aspx/shell32.SHFileOperation

2

di Microsoft Windows API Code Pack contiene questa funzionalità.

Per ottenere la cartella del Cestino, utilizzare

Microsoft.WindowsAPICodePack.Shell.KnownFolderHelper.FromPath("::{645FF040-5081-101B-9F08-00AA002F954E}"); 

Non ho idea di che cosa significa quella stringa, ma era inclusa nella documentazione come il riferimento al Cestino.

Spero che questo aiuti :)

+0

Quella stringa è un GUID, molto probabilmente l'identificativo per il file riciclato. – mgbowen

+1

Non sono sicuro, ma non è questo il cestino globale? Come posso verificare se qualche cartella (data dal suo percorso) è collegata a questa cartella globale? – mafu

+0

Non ho scavato troppo in profondità quando ho scritto la mia risposta, avevo pensato che il codice sopra avrebbe reso relativamente facile ottenere un elenco di elementi nel Cestino. Dovrò guardarmi intorno più tardi stasera e tornare da te. –