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

maf*_*afu 12 c# recycle-bin

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

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

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

Abe*_*bel 7

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

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

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
}
Run Code Online (Sandbox Code Playgroud)

为每个驱动器重复伪造的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
Run Code Online (Sandbox Code Playgroud)

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

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

更新:替代方法有SHGetSpecialFolderPath,SHGetSpecialFolderLocation,ShellAPI.SHGetFolderLocationSHGetPathFromIDList所有的失败,是相同的:无论是一个空的结果或错误.我测试了回收站和AppData的所有功能(确保我使用了正确的参数).

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