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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/936397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 12:34:45  来源:igfitidea点击:

Finding the Recycle Bin on a local NTFS drive

windowswinapifilesystemsntfsrecycle-bin

提问by DougN

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.

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

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)

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

Can anyone point me to a definitive answer?

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

Thanks

谢谢

UPDATE: Aware of CSIDL_BITBUCKETand the functions that use it. From everything I've read though, it points to a virtualdirectory 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)

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

采纳答案by DougN

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.

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

请注意,我在下面包含了两个 GetFolderCLSID 函数。Raymond Chen 的更简单,但它在 Windows 2000 上不起作用。另一个实现更长,但似乎在任何地方都有效。

Call like: CString recycleDir = FindRecycleBinOnDrive(L"C:\");

调用方式: 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;
//}

回答by John Topley

回答by botismarius

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:

在调试 shell32.dll 之后,我发现对于每个版本的 Windows,回收路径都是硬编码的,而且还取决于该驱动器的文件系统。我已经在 Windows XP、Vista 和 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:

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

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

维基文章提出了相同的事实:http: //en.wikipedia.org/wiki/Recycle_Bin_%28Windows%29

回答by Michael Petrotta

In Win32, use SHGetSpecialFolderLocation. Pass CSIDL_BITBUCKETas the CDIL parameter.

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