3

我正在尝试编写一些简单的代码,这些代码将返回本地驱动器上回收站的目录。似乎这很简单——应该是谷歌上的一千个答案。还没找到:(

我发现 FAT 和 NTFS 驱动器具有不同的基本名称(RECYCLED 和 RECYCLER)。我发现'the'回收站是一个虚拟文件夹,它结合了机器上所有驱动器的回收站。

我还没有找到一种找到 C: 驱动器的回收站目录的方法——即使在越南语(或任何其他非英语)机器上也是如此。(我找不到任何帖子表明“回收站”是否国际化)

谁能给我一个明确的答案?

谢谢

更新:了解CSIDL_BITBUCKET和使用它的功能。从我读过的所有内容来看,它指向一个虚拟目录,该目录是该用户在所有驱动器上删除的所有文件的联合。寻找物理回收站目录(据我所知,在我的 Vista 上,它似乎是 C:\$Recycle.Bin)

4

4 回答 4

2

Raymond Chen 给出了答案——我怎么知道一个目录真的是一个回收站

于 2009-06-02T10:07:52.543 回答
2

使用 Raymond Chen 的建议和其他人的技术(不记得我在哪里找到它)我提出了一个函数,它将在驱动器上找到回收站目录。该函数循环遍历根目录中的目录,查看隐藏和/或系统目录。当它找到一个时,它会检查子子目录以查找具有 CLSID_Recycle Bin 的子目录。

请注意,我在下面包含了两个 GetFolderCLSID 函数。Raymond Chen 的比较简单,但它不适用于 Windows 2000。另一种实现较长,但似乎可以在任何地方使用。

调用如下: CString recycleDir = FindRecycleBinOnDrive(L"C:\");

CString FindRecycleBinOnDrive(LPCWSTR path)
{
    CString search;
    search.Format(L"%c:\\*", path[0]);
    WIN32_FIND_DATA fd = {0};
    HANDLE fHandle = FindFirstFile(search, &fd);
    while(INVALID_HANDLE_VALUE != fHandle)
    {
        if(FILE_ATTRIBUTE_DIRECTORY == (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) //only check directories
        {
            if(0 != (fd.dwFileAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))) //only check hidden and/or system directories
            {
                //the recycle bin directory itself won't be marked, but a SID-specific child directory will, so now look at them
                CString childSearch;
                childSearch.Format(L"%c:\\%s\\*", path[0], fd.cFileName);
                WIN32_FIND_DATA childFD = {0};
                HANDLE childHandle = FindFirstFile(childSearch, &childFD);
                while(INVALID_HANDLE_VALUE != childHandle)
                {
                    if((FILE_ATTRIBUTE_DIRECTORY == (childFD.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) && //only check directories
                        (childFD.cFileName[0] != L'.')) //don't check . and .. dirs
                    {
                        CString fullPath;
                        fullPath.Format(L"%c:\\%s\\%s", path[0], fd.cFileName, childFD.cFileName);
                        CLSID id = {0};
                        HRESULT hr = GetFolderCLSID(fullPath, id);
                        if(SUCCEEDED(hr))
                        {
                            if(IsEqualGUID(CLSID_RecycleBin, id))
                            {
                                FindClose(childHandle);
                                FindClose(fHandle);
                                //return the parent (recycle bin) directory
                                fullPath.Format(L"%c:\\%s", path[0], fd.cFileName);
                                return fullPath;
                            }
                        }
                        else
                        {
                            Log(logERROR, L"GetFolderCLSID returned %08X for %s", hr, fullPath);
                        }
                    }

                    if(FALSE == FindNextFile(childHandle, &childFD))
                    {
                        FindClose(childHandle);
                        childHandle = INVALID_HANDLE_VALUE;
                    }
                }
            }
        }
        if(FALSE == FindNextFile(fHandle, &fd))
        {
            FindClose(fHandle);
            fHandle = INVALID_HANDLE_VALUE;
        }
    }
    _ASSERT(0);
    return L"";
}


//Works on Windows 2000, and even as Local System account
HRESULT GetFolderCLSID(LPCWSTR path, CLSID& pathCLSID)
{
    LPMALLOC pMalloc = NULL;
    HRESULT hr = 0;
    if (SUCCEEDED(hr = SHGetMalloc(&pMalloc))) 
    {
        LPSHELLFOLDER pshfDesktop = NULL;
        if (SUCCEEDED(hr = SHGetDesktopFolder(&pshfDesktop))) 
        {
            LPITEMIDLIST pidl = NULL;
            DWORD dwAttributes = SFGAO_FOLDER;
            if (SUCCEEDED(hr = pshfDesktop->ParseDisplayName(NULL, NULL, (LPWSTR)path, NULL, &pidl, &dwAttributes))) 
            {
                LPPERSIST pPersist = NULL;
                if (SUCCEEDED(hr = pshfDesktop->BindToObject(pidl, NULL, IID_IPersist, (LPVOID *) &pPersist))) 
                {
                    hr = pPersist->GetClassID(&pathCLSID); 
                    pPersist->Release();
                } 
                pMalloc->Free(pidl);
            } 
            pshfDesktop->Release();
        } 
        pMalloc->Release();
    }
    return hr;
}


//Not supported on Windows 2000 since SHParseDisplayName wasn't implemented then
//HRESULT GetFolderCLSID(LPCWSTR pszPath, CLSID& pathCLSID)
//{
//  SHDESCRIPTIONID did = {0};
//  HRESULT hr = 0;
//  LPITEMIDLIST pidl = NULL;
//  if (SUCCEEDED(hr = SHParseDisplayName(pszPath, NULL, &pidl, 0, NULL))) //not supported by Windows 2000
//  {
//      IShellFolder *psf = NULL;
//      LPCITEMIDLIST pidlChild = NULL;
//      if (SUCCEEDED(hr = SHBindToParent(pidl, IID_IShellFolder, (void**)&psf, &pidlChild))) 
//      {
//          hr = SHGetDataFromIDList(psf, pidlChild, SHGDFIL_DESCRIPTIONID, &did, sizeof(did));
//          psf->Release();
//          pathCLSID = did.clsid;
//      }
//      CoTaskMemFree(pidl);
//  }
//  return hr;
//}
于 2009-06-03T15:58:59.173 回答
1

有点晚了,但也许迟到总比没有好......

在调试 shell32.dll 之后,我发现对于每个版本的 windows,回收路径都是硬编码的,而且还取决于该驱动器的文件系统。我已经在 Windows XP、Vista 和 Windows7 上对此进行了测试:

设 X: 为我们要获取回收站路径的驱动器,设 SID 为当前用户的 SID,则:


    switchif(OsType) {
        case WindowsXP:
        {
            if(PartitionType("X:") == NTFS)
            {
                printf("Path is: X:\\Recycler\\SID\\");
            }
            else
            {
                printf("Path is X:\\RECYCLED\\");
            }
        }

        case WindowsVista:
        case Windows7:
        {
            if(PartitionType("X:") == NTFS)
            {
                printf("Path is: X:\\$Recycle.bin\\SID\\");
            }
            else
            {
                printf("Path is X:\\$RECYCLE.BIN\\");
            }
        }
    }

一篇 wiki 文章提供了相同的事实: http ://en.wikipedia.org/wiki/Recycle_Bin_%28Windows%29

于 2009-09-09T21:59:57.873 回答
0

在 Win32 中,使用SHGetSpecialFolderLocation将CSIDL_BITBUCKET作为 CDIL 参数传递。

于 2009-06-01T19:51:30.740 回答