2012-03-23 4 views

ответ

4

Если вы готовы использовать Windows API, то самый простой способ сделать это - позвонить SHFileOperation. Используйте операцию FO_DELETE и не забудьте удвоить нулевое завершение имени вашего каталога.

+0

Имейте в виду, что SHFileOperation отлично подходит для приложений пользовательского режима, но не работает при вызове из службы Windows, особенно если используется Impersonation для удаления каталога на общем сетевом ресурсе UNC. Для этого сценария вам нужно будет выполнить работу с ворчанием и использовать FindFirstFile()/FindNext() с помощью DeleteFile()/RemoveDirectory() жесткого пути. – WebDrive

3

Как правило, если библиотечный метод недоступен, это делается путем рекурсии. Функция выполняет итерацию всех записей в каталоге, удаляя «обычные» файлы и называя себя любым найденным путем. Это разрушает целые деревья каталогов (моя версия Windows имеет явные проверки пути, прошедшего для предотвращения уничтожения папок ОС в случае случайного прохождения суицидального параметра).

2

Это может быть неточным, но рассмотреть вопрос об использовании

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

Это некрасиво, но это слишком просто игнорировать. В нем также есть все, что нужно для работы с файлами на сетевых ресурсах. Независимо от того, какое решение вы придумали, вероятно, является (неполной и/или неправильной) переоценкой rd, поэтому вызов внешнего процесса будет действительно хорошим повторным использованием кода. ;-)

+0

Повторное использование и невозможность повторного использования кода даже с ошибкой компиляции, если rd не существует , Для очень маленькой программы это может быть полезно и правильно, для долгой жизни большие, меньше. Лично я всегда проверял, действительно ли эта команда существует. –

+0

@phresnel: вопрос касается только для систем Windows, и по умолчанию «rd» доступен для всех систем Windows. Я выхожу на конечность и утверждаю, что доступный «rd» более вероятен, чем доступный «SHFileOperation» («SHFileOperation» существует только после Windows XP, и он устарел в Windows Vista). –

+0

Вероятность менее важна для меня. Лично я не буду компилировать ошибку времени, если какой-либо функции не существует; с системой вы никогда не компилируете ошибки времени. Как сказано, для небольших системных программ это может быть хорошо. Но я бы советовал против этого для более крупных или долгоживущих программ. Вы никогда не знаете, что через 5, 10, 15 лет. Если вдруг все перейдут на Mac или Linux, то, конечно, вы захотите, чтобы ваша корова с налитом бегала на этой платформе. –

7

Лучшим решением, если вы можете использовать его, является boost::filesystem::remove_all. Таким образом, вам не нужно беспокоиться о специфике платформы. Я не знаю ни одного другого независимого от платформы решения; обычный способ в противном случае включал бы чтение каталога и рекурсивное сведение его (но способ чтения каталога также использует boost::filesystem или системный код).

2

Согласно MSDN, SHFileOperation не является потокобезопасным при использовании с относительными путями. Его можно безопасно использовать только с абсолютными путями.

Я рекомендую использовать этот код вместо:

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; 
    } 
} 

Если вы хотите использовать мой код «как есть», вы будете нуждаться в этих заголовках и такие в верхней части файла 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; 

... и думаю есть.

Мой код основан на этой статье:

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

Я настоятельно рекомендую никогда не использовать SHFileOperation, помимо вопросов безопасности, он был заменен IFileOperation, поскольку Windows Vista.

Надеюсь, это поможет!

Смежные вопросы