如何判断目录是C#中的回收站?

给定一个文件夹,我怎么知道它是一个回收站? 我找到了C ++的答案 ,但没有找到C#的答案 。

我的第一个想法是检查FileAttributes.System(在我的情况下这将是一个可接受的近似值),但实际上该标志在回收文件夹中被清除。

使用硬编码文件夹名称的原始解决方案是不可能的(我们毕竟是在2009年)。

这里有一点问题。 Windows回收站是一个虚拟文件夹,实际上并不存在。 您看到的文件实际上并不在该文件夹中,它们是磁盘上已重命名为特殊名称的现有文件的表示forms,它将它们从可见文件系统中“删除”,而不是从物理系统中删除。

您可以通过使用win32 API询问文件夹位置来自行“certificate”这一点。 它将返回E_FAIL作为回收站,但不会返回其他文件夹(请参阅pinvoke.net上的SHGetKnownFolderPath ( 以及MSDN上 ),了解您可以使用的所有常量以及运行此代码所需的声明):

 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 } 

每个驱动器重复伪造的foldername “$ Recycle.bin” 。 隐藏名称不存储在注册表中,并且API无法访问它。 之前建议的KnownFolderHelper也不会检索此信息(同一个lib有一个获取回收站的命名方法,它也有一个GetPath ,它将变为空)。

但一切都不会丢失。 这个假的不存在的“文件名”或“文件夹名称”包含一个看起来像“S-1-5-21-2703390745-3900912742-210389625-1000”的隐藏文件(你的不同)。 这是找出某个文件名是否实际上是回收站的虚拟目录的两种“可靠”方法之一(另一种方式是:通过SHFileOperation删除文件, 在此解释 ,并检查它是否出现在您拥有的文件夹中) :

 string [] entries = Directory.GetFileSystemEntries(@"c:\$Recycle.bin", "?-?-?-??*"); if(entries.Length > 0) // we have a winner else // no, not the recycle bin 

注意:我不知道其他win32版本上的隐藏文件夹是什么,你需要进行一些实验。 它们都设置了系统和隐藏标志,看起来像一个受损的GUID。

API文档对此并不十分清楚,但如果您需要确认, 此页面会说明确实没有可以检索的路径( 较旧的CSIDL相关页面不太清楚)。

更新:使用SHGetSpecialFolderPathSHGetSpecialFolderLocationShellAPI.SHGetFolderLocationSHGetPathFromIDList替代方法都会失败:无论是空结果还是错误。 我测试了回收站和AppData的所有function(确保我使用了正确的参数)。

只有ShGetPathFromIDListEx上的文档明确说明, “除了UNC打印机名称,如果pidl参数指定的位置不是文件系统的一部分,则此函数失败。”

如您所述,大多数与回收站相关的方法都是用C ++编写的。 你可以使用C ++的托管扩展在你的应用程序中创建一个包装类,然后你必须像这样使用DLLImport:

 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 ); } } 

还有一些文章用C#做了一些其他方式,其中大多数使用PInvoke或依赖于其名称中包含$ Recycle的文件夹。 以下是我为此主题找到的一些链接

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

Microsoft的Windows API代码包包含此function。

要获取回收站的文件夹,请使用

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

我不知道该字符串的含义,但它作为对回收站的引用包含在文档中。

希望这可以帮助 :)