2012-03-23 21 views

Respuesta

4

Si está preparado para usar la API de Windows, la manera más fácil de hacerlo es llamar al SHFileOperation. Use la operación FO_DELETE y no olvide doblemente el nombre del directorio.

+0

Tenga en cuenta que SHFileOperation funciona muy bien para las aplicaciones del Modo de usuario, pero no funciona cuando se llama desde un Servicio de Windows, especialmente si se utiliza Suplantación para eliminar un directorio en un recurso compartido de red UNC. Para este escenario necesitarás hacer el trabajo pesado y usar FindFirstFile()/FindNext() con DeleteFile()/RemoveDirectory() de la manera difícil – WebDrive

3

Normalmente, si no hay un método de biblioteca disponible, esto se realiza por recursión. Una función itera todas las entradas de directorio, borrando archivos 'ordinarios' y llamándose a sí mismo con cualquier ruta de directorio encontrada. Esto destruye árboles de directorios completos (mi versión de Windows tiene comprobaciones explícitas de la ruta pasada para evitar que destruya las carpetas del sistema operativo en caso de pasar accidentalmente un parámetro suicida).

2

Esto puede ser escaso, pero considerar el uso de

system("rd /s /q ..."); 

Es feo, pero es demasiado simple como para ignorarlo. También tiene todos los elementos "cómo lidiar con los archivos en las redes compartidas". Cualquier solución que se te ocurra es probablemente una (incompleta y/o incorrecta) reimplementación de rd, por lo que llamar al proceso externo sería una buena reutilización del código. ;-)

+0

Reutilización y anulación del código sin siquiera un error de compilación si rd no existe . Para un programa muy pequeño, esto podría ser útil y correcto, para los de larga duración, menos. Personalmente, siempre verificaría si ese comando realmente existe. –

+0

@phresnel: la pregunta es solo para sistemas Windows y 'rd' está disponible en todos los sistemas Windows de manera predeterminada. Me arriesgaría y afirmaría que 'rd' está disponible es más probable que 'SHFileOperation' esté disponible ('SHFileOperation' solo ha existido desde Windows XP, y ha quedado en desuso con Windows Vista). –

+0

La probabilidad es menos relevante para mí. Personalmente, quiero un error de tiempo de compilación si alguna funcionalidad no está allí; con el sistema nunca tendrá errores de compilación. Como se dijo, para programas pequeños, específicos del sistema, esto podría estar bien. Pero recomendaría que no se aplique a programas de mayor duración o duración. Nunca se sabe lo que hay en 5, 10 o 15 años a partir de ahora. Si de pronto todos hubieran cambiado a Mac o Linux, seguramente también querrían que su dinero en efectivo se ejecutara en esa plataforma. –

7

La mejor solución, si puede usarla, es boost::filesystem::remove_all. De esta forma, no tiene que preocuparse por las cosas específicas de la plataforma. No conozco ninguna otra solución independiente de plataforma; la forma usual de lo contrario implicaría leer el directorio y descender recursivamente (pero la forma de leer el directorio también usa boost::filesystem o el código dependiente del sistema).

2

Según MSDN, SHFileOperation no es seguro para subprocesos cuando se utiliza con rutas de acceso relativas. Solo se puede usar de forma segura con rutas absolutas.

recomiendo el uso de este código en su lugar:

double directory_delete(char *pathname) 
{ 
    string str(pathname); 
    if (!str.empty()) 
    { 
     while (*str.rbegin() == '\\' || *str.rbegin() == '/') 
     { 
      str.erase(str.size()-1); 
     } 
    } 
    replace(str.begin(),str.end(),'/','\\'); 

    struct stat sb; 
    if (stat((char *)str.c_str(),&sb) == 0 && 
     S_ISDIR(sb.st_mode)) 
    { 
      HANDLE hFind; 
      WIN32_FIND_DATA FindFileData; 

      TCHAR DirPath[MAX_PATH]; 
      TCHAR FileName[MAX_PATH]; 

      _tcscpy(DirPath,(char *)str.c_str()); 
      _tcscat(DirPath,"\\*"); 
      _tcscpy(FileName,(char *)str.c_str()); 
      _tcscat(FileName,"\\"); 

      hFind = FindFirstFile(DirPath,&FindFileData); 
      if (hFind == INVALID_HANDLE_VALUE) return 0; 
      _tcscpy(DirPath,FileName); 

      bool bSearch = true; 
      while (bSearch) 
      { 
       if (FindNextFile(hFind,&FindFileData)) 
       { 
        if (!(_tcscmp(FindFileData.cFileName,".") && 
         _tcscmp(FindFileData.cFileName,".."))) continue; 
        _tcscat(FileName,FindFileData.cFileName); 
        if ((FindFileData.dwFileAttributes & 
        FILE_ATTRIBUTE_DIRECTORY)) 
        { 
         if (!directory_delete(FileName)) 
         { 
          FindClose(hFind); 
          return 0; 
         } 
         RemoveDirectory(FileName); 
         _tcscpy(FileName,DirPath); 
        } 
        else 
        { 
         if (FindFileData.dwFileAttributes & 
          FILE_ATTRIBUTE_READONLY) 
          _chmod(FileName, _S_IWRITE); 

         if (!DeleteFile(FileName)) 
         { 
          FindClose(hFind); 
          return 0; 
         } 
         _tcscpy(FileName,DirPath); 
        } 
       } 
       else 
       { 
        if (GetLastError() == ERROR_NO_MORE_FILES) 
         bSearch = false; 
        else 
        { 
         FindClose(hFind); 
         return 0; 
        } 
       } 
      } 
      FindClose(hFind); 

      return (double)(RemoveDirectory((char *)str.c_str()) == true); 
    } 
    else 
    { 
     return 0; 
    } 
} 

Si desea utilizar mi código "tal cual", tendrá que estas cabeceras y tal en la parte superior de su archivo CPP:

#include <windows.h> // winapi 
#include <sys/stat.h> // stat 
#include <tchar.h> // _tcscpy,_tcscat,_tcscmp 
#include <string> // string 
#include <algorithm> // replace 

using namespace std; 

... y creo que eso es todo.

Mi código se basa en este artículo:

http://www.codeguru.com/cpp/w-p/files/folderdirectorymaintenance/article.php/c8999/Deleting-a-Directory-Along-with-SubFolders.htm

os recomiendo no usar nunca SHFileOperation, aparte de los problemas de seguridad, que fue sustituido por IFileOperation desde Windows Vista.

Espero que esto ayude!

Cuestiones relacionadas