Pregunta

Estoy tratando de escribir un código simple que devolverá el directorio de la papelera de reciclaje en una unidad local. Parece que sería simple - debe haber un millar de respuestas en Google. No se han encontrado con todo: (

He encontrado que las unidades FAT y NTFS tienen diferentes nombres de bases (reciclado y RECYCLER). He descubierto que 'la' papelera de reciclaje es una carpeta virtual que combina las papeleras de reciclaje de todos los accionamientos en la máquina.

Lo que no he encontrado es una manera de encontrar C: directorio de la papelera de reciclaje de la unidad - incluso en un vietnamita (o cualquier otro no-Inglés) de la máquina. (No hay mensajes que puedo encontrar indican si "RECICLADOR" se internacionalizó o no)

Puede alguien me punto a una respuesta definitiva?

Gracias

ACTUALIZACIÓN: Consciente de CSIDL_BITBUCKET y las funciones que lo utilizan. De todo lo que he leído, sin embargo, que apunta a un directorio Virtual , que es la unión de todos los archivos borrados por ese usuario en todas las unidades. Buscando el directorio de la papelera de reciclaje física (en mi Vista parece ser C: \ $ Recycle.bin la medida de lo que puedo decir)

¿Fue útil?

Solución 2

Consejo de utilización de Raymond Chen, y la técnica de otra persona (no puede recordar dónde lo encontré) presento una función que se encuentra el directorio de la papelera de reciclaje en una unidad. Los ciclos de función a través de los directorios en el directorio raíz mirando directorios ocultos y / o del sistema. Cuando encuentra uno, comprueba los subdirectorios niño buscando uno que tiene CLSID_Recycle Bin.

Tenga en cuenta que he incluido dos funciones GetFolderCLSID a continuación. Raymond Chen es el más simple, pero no funciona en Windows 2000. La otra aplicación es más largo, pero parece que funciona en todas partes.

Llamada como: 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;
//}

Otros consejos

Un poco tarde, pero tal vez mejor tarde que nunca ...

Después de la depuración shell32.dll, he encontrado que para cada versión de Windows la ruta de reciclaje es codificado y, también, depende del sistema de archivos de esa unidad. He probado esto en Windows XP, Vista y Windows 7:

Sea X: ser la unidad que queremos obtener la ruta a la papelera de reciclaje y dejar que sea el SID SID del usuario actual y, a continuación:


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

Un artículo de wiki presenta los mismos hechos: http://en.wikipedia.org/wiki/Recycle_Bin_%28Windows%29

En Win32, utilice SHGetSpecialFolderLocation . Pase CSIDL_BITBUCKET como el parámetro CDIL.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top