给定一个文件夹,如何判断它是否是回收站?我已经找到了一个C++的答案,但没有C#的。
我的第一个想法是检查FileAttributes.System(在我的情况下这是可以接受的近似值),但实际上该标志在回收站文件夹中被清除了。
使用硬编码的文件夹名称的粗暴解决方案是不可取的(毕竟我们是在2009年)。
给定一个文件夹,如何判断它是否是回收站?我已经找到了一个C++的答案,但没有C#的。
我的第一个想法是检查FileAttributes.System(在我的情况下这是可以接受的近似值),但实际上该标志在回收站文件夹中被清除了。
使用硬编码的文件夹名称的粗暴解决方案是不可取的(毕竟我们是在2009年)。
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
SHGetSpecialFolderPath
,SHGetSpecialFolderLocation
,ShellAPI.SHGetFolderLocation
和SHGetPathFromIDList
的替代方法都会失败,结果要么为空,要么出现错误。我为回收站和AppData测试了所有函数(以确保使用正确的参数)。
只有ShGetPathFromIDListEx
的文档明确说明了这一点,引用:“除了UNC打印机名称外,如果pidl参数指定的位置不是文件系统的一部分,则此函数将失败。”。
微软的Windows API Code Pack包含此功能。
要获取回收站文件夹,请使用以下方法:
Microsoft.WindowsAPICodePack.Shell.KnownFolderHelper.FromPath("::{645FF040-5081-101B-9F08-00AA002F954E}");
正如您所提到的,大多数与回收站相关的方法都是用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