在C#中,我如何确定一个目录是回收站?

12

给定一个文件夹,如何判断它是否是回收站?我已经找到了一个C++的答案,但没有C#的。

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

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


4
你能不能将C++的解决方案转换成C#呢?如果你在这里发布,你可能会得到帮助。从C#调用API函数肯定是可行的,也不是魔法。 - Joey
这是相关框中的第一个问题;)我会添加直接链接。 - mafu
当然,如果可能的话,我强烈希望使用.NET内置的解决方案。 - mafu
从我的回答中,您可能已经了解到,实际上并没有这样的东西。我知道您不喜欢它,但请考虑硬编码文件夹名称,这比我下面解释的更彻底的方法要容易得多:http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic61430.aspx - Abel
3个回答

7
这里有一个小问题。Windows回收站是一个虚拟文件夹,实际上并不存在。您看到的文件实际上不在那个文件夹中,它们是现有文件在磁盘上被重命名为特殊名称的表示形式,这将它们从可见文件系统中“移除”,但不会从物理文件系统中删除。
您可以通过使用win32 API请求文件夹位置来自行验证此内容。对于回收站,它会返回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
}

对于每个驱动器,虚假的文件夹名称"$Recycle.bin"都会重复出现。该隐藏名称未存储在注册表中,并且无法通过API访问。先前建议的KnownFolderHelper也无法检索此信息(同一库具有一个用于获取回收站的命名方法,它还具有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测试了所有函数(以确保使用正确的参数)。

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


3

微软的Windows API Code Pack包含此功能。

要获取回收站文件夹,请使用以下方法:

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

我不知道那个字符串是什么意思,但它作为回收站的参考文档被包含在内。
希望这有所帮助 :)

那个字符串是GUID,很可能是回收文件的标识符。 - user153498
1
我不确定,但那不是全局回收站吗?我该如何检查某个文件夹(通过其路径给出)是否链接到此全局文件夹? - mafu
我在回答时没有深入挖掘,我假设上述代码会使得获取回收站中项目列表相对容易。我晚些时候会再看看并回复你。 - Eric Smith
我知道这篇文章已经四年了。但是值得一提的是,那个GUID和其他一些GUID被存储在注册表的子键中:HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace(对于x64机器,还有Wow6432Node路径)。默认的值名称为“Recycle Bin”。其他位置也在那里列出,例如ControlPanelHome、Public Folder、Documents等。 - DJH
无法在Windows 8 x64上运行,它会显示路径不存在。 - ElektroStudios

2

正如您所提到的,大多数与回收站相关的方法都是用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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接