代码之家  ›  专栏  ›  技术社区  ›  DougN

在本地NTFS驱动器上查找回收站

  •  3
  • DougN  · 技术社区  · 15 年前

    我试图编写一些简单的代码,返回本地驱动器上回收站的目录。看起来很简单——应该是谷歌上的一千个答案。尚未找到一个:(

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

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

    有人能给我一个明确的答案吗?

    谢谢

    更新:了解 CSIDL_BITBUCKET 以及使用它的功能。但从我读到的所有内容来看,它指向了一个 事实上的 目录,该目录是该用户在所有驱动器上删除的所有文件的联合。正在查找物理回收站目录(据我所知,在我的Vista上它似乎是C:\$recycle.bin)

    4 回复  |  直到 15 年前
        1
  •  2
  •   John Topley    15 年前
        2
  •  2
  •   DougN    15 年前

    利用Raymond Chen的建议和其他人的技术(不记得在哪里找到它),我提供了一个函数,可以在驱动器上查找回收站目录。该函数在根目录中的目录中循环,查看隐藏目录和/或系统目录。当它找到一个时,它会检查子目录,寻找一个包含CLSID_回收站的子目录。

    调用如下:CString recycleDir=findRecycleBinDrive(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;
    //}
    
        3
  •  1
  •   botismarius    15 年前

    有点晚了,但也许晚了总比不到好。。。

    调试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\\");
                }
            }
        }
    
    

    一篇维基文章呈现了同样的事实: http://en.wikipedia.org/wiki/Recycle_Bin_%28Windows%29

        4
  •  0
  •   Michael Petrotta user3140870    15 年前

    在Win32中,使用 SHGetSpecialFolderLocation . 通过 CSIDL_BITBUCKET 作为CDIL参数。