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

发布于 2024-07-21 19:43:44 字数 455 浏览 8 评论 0原文

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

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

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

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

谢谢

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

I'm trying to write some simple code that will return the directory for the recycle bin on a local drive. Seems like it would be simple -- should be a thousand answers on Google. Haven't found one yet :(

I HAVE found that FAT and NTFS drives have different base names (RECYCLED and RECYCLER). I've found that 'the' recycle bin is a virtual folder that combines the recycle bins of all drives on the machine.

What I haven't found is a way to find C: drive's recycle bin directory -- even on a Vietnamese (or any other non-English) machine. (No posts I can find indicate whether "RECYCLER" gets internationalized or not)

Can anyone point me to a definitive answer?

Thanks

UPDATE: Aware of CSIDL_BITBUCKET and the functions that use it. From everything I've read though, it points to a virtual directory which is the union of all deleted files by that user on all drives. Looking for the physical recycle bin directory (on my Vista it appears to be C:\$Recycle.Bin as far as I can tell)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风尘浪孓 2024-07-28 19:43:44

使用 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;
//}

Using Raymond Chen's advice, and someone else's technique (can't remember where I found it) I present a function that will find the Recycle Bin directory on a drive. The function cycles through the directories in the root directory looking at hidden and/or system directories. When it finds one, it checks the child subdirectories looking for one that has CLSID_Recycle Bin.

Note that I've included two GetFolderCLSID functions below. Raymond Chen's is the simpler one, but it doesn't work on Windows 2000. The other implementation is longer, but appears to work everywhere.

Call like: 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;
//}
剧终人散尽 2024-07-28 19:43:44

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

In Win32, use SHGetSpecialFolderLocation. Pass CSIDL_BITBUCKET as the CDIL parameter.

隔岸观火 2024-07-28 19:43:44

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

在调试 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

A little bit late, but perhaps better late than never...

After debugging shell32.dll, I have found that for each version of windows the recycle path is hardcoded and, also, depends on the filesystem of that drive. I have tested this on Windows XP, Vista and Windows7:

Let X: be the drive we want to get the path to the recycle bin and let SID be the SID of the current user, then:


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

A wiki article presents the same facts:
http://en.wikipedia.org/wiki/Recycle_Bin_%28Windows%29

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文