Wie kann ich feststellen, dass ein Verzeichnis der Papierkorb in C # ist?
-
22-09-2019 - |
Frage
Bei einem Ordner, wie kann ich sagen, dass es ein Papierkorb ist? Ich habe eine Antwort für C ++, aber nicht für C #.
Meine erste Idee war für FileAttributes.System zu überprüfen (was eine akzeptable Annäherung in meinem Fall wäre), aber eigentlich, dass Flag wird auf dem Papierordner gelöscht.
Crude Lösungen fest einprogrammierte Ordnernamen verwenden, sind nicht in Frage (wir sind im Jahr 2009, nachdem alle).
Lösung
Es gibt ein kleines Problem. Der Windows-Papierkorb ist ein virtueller Ordner und existiert nicht wirklich. Die Dateien, die Sie sehen, sind nicht wirklich in diesem Ordner, sind sie die Darstellung der vorhandenen Dateien auf der Festplatte, die mit einem speziellen Namen umbenannt wurden, die „entfernt“, um sie aus dem sichtbaren Dateisystem, aber nicht die physischen.
Sie können „Beweis“ diese für sich selbst, indem für den Ordner fragen die win32-API. Es wird wieder E_FAIL
für den Papierkorb, aber nicht für andere Ordner (siehe SHGetKnownFolderPath auf pinvoke .net ( und auf MSDN ) für alle Konstanten können Sie verwenden, und die für diesen Code auszuführen benötigt Erklärungen):
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
}
Die gefälschten folder "$ Recycle.bin" wird für jedes Laufwerk wiederholt. Die versteckte Name ist nicht in der Registry gespeichert, und es ist von der API als solche nicht zugänglich. Je früher vorgeschlagen KnownFolderHelper nicht abrufen diese Informationen entweder (die gleiche lib für das Erhalten des Papierkorbs eine benannte Methode hat, hat es auch eine GetPath
, wird es wieder auftauchen leer).
Aber nicht alles verloren ist. Diese Fälschung nicht vorhandene „Dateiname“ oder „Ordnername“ enthält eine versteckte Datei, die wie etwas aussieht „S-1-5-21-2703390745-3900912742-210389625-1000“ (Ihr wird anders). Es ist eines von zwei „zuverlässigen“ Möglichkeiten, um herauszufinden, ob ein bestimmte Dateiname ist eigentlich ein virtuelles Verzeichnis des Papierkorbs (die andere Art und Weise zu sein: Löschen eine Datei durch SHFileOperation
, erklärt hier , und prüfen, ob es in dem Ordner angezeigt Sie haben):
string [] entries = Directory.GetFileSystemEntries(@"c:\$Recycle.bin", "?-?-?-??*");
if(entries.Length > 0)
// we have a winner
else
// no, not the recycle bin
Hinweis: Ich weiß nicht, was die versteckten Ordner auf anderen win32-Versionen sind, you'l ein wenig experimentieren. Sie alle haben das System und verstecken Flag gesetzt und aussieht wie ein verstümmelten GUID.
Die API-Dokumentation ist nicht sehr klar darüber, aber wenn Sie eine Bestätigung benötigen, diese Seite erklärt , dass es wirklich keinen Weg, der (die ältere CSIDL bezogene Seite auf es viel weniger klar ist).
Update: alternative Ansätze mit SHGetSpecialFolderPath
, SHGetSpecialFolderLocation
, ShellAPI.SHGetFolderLocation
und SHGetPathFromIDList
alle mit dem gleichen fehlschlagen: entweder ein leeres Ergebnis oder ein Fehler. Getestet habe ich alle Funktionen sowohl für Papierkorb und für AppData (sicher sein verwendete ich die richtigen Parameter).
Nur die Dokumentation auf ShGetPathFromIDListEx
sagte, es ausdrücklich, Zitat:. „mit Ausnahme UNC Druckernamen, wenn der Ort durch den PIDL Parameter angegeben nicht Teil des Dateisystems ist, versagt diese Funktion“
Andere Tipps
Microsofts Windows-API-Code-Pack diese Funktionalität enthält.
Um den Ordner aus dem Papierkorb zu erhalten, verwendet
Microsoft.WindowsAPICodePack.Shell.KnownFolderHelper.FromPath("::{645FF040-5081-101B-9F08-00AA002F954E}");
Ich habe keine Ahnung, was die String-Mittel, aber es war in der Dokumentation als Referenz in den Papierkorb enthält.
Hope, das hilft:)
Die meisten der Papierkorb bezogenen Methoden wurden in C ++ geschrieben, wie Sie erwähnt. Sie könnten eine Wrapper-Klasse in Ihrer Anwendung erstellen, um die Verwendung von verwaltete Erweiterungen
: C ++ , dann werden Sie DLLImport wie diese verwenden müssenusing 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 );
}
}
Es gibt auch Artikel gibt, die mit C # diese etwas andere Art und Weise zu tun, die meisten von ihnen verwenden PInvoke oder stützen sich auf den Ordner $ Recycle in seinem Namen hat. Im Folgenden sind ein paar Links Ich habe zu diesem Thema gefunden