На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела FAQ в группе разделов С++.
1. Раздел FAQ предназначен для публикации готовых статей.
2. Здесь нельзя задавать вопросы, для этого существуют соответствующие разделы:
Чистый С++
Visual C++ / MFC / WTL / WinApi
Borland C++ Builder
COM / DCOM / ActiveX / ATL
Сопутствующие вопросы
3. Внимание, все темы и сообщения в разделе премодерируются. Любое сообщение или тема будут видны остальным участникам только после одобрения модератора.
Модераторы: B.V., Qraizer
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Удаление директории
    Очень часто в форуме возникают вопросы про удаление директорий.
    Штука достаточно простая, большинство бы и так догадалось как делать, но иногда нужно просто держать сухим нужный кусок кода, вынуть его из заначки и применить.

    ExpandedWrap disabled
      BOOL    RemoveDir( IN LPCTSTR szDir)
      {
          BOOL fRet = FALSE;
          if( !szDir) return fRet;
       
          size_t tReplaceLen = 1;
          WIN32_FIND_DATA fd = {};
       
          // Формируем строку пути для поиска файлов
          std::basic_string< TCHAR > stPath( szDir);
          stPath += _T( "\\*");
       
          HANDLE hFind = FindFirstFile( stPath.c_str(), &fd);
          if( hFind != INVALID_HANDLE_VALUE)
          {
              fRet = TRUE;
              do {
                  // Игнорируем вхождения в каталог
                  if( !(_tcscmp( fd.cFileName, _T( ".")) && _tcscmp( fd.cFileName, _T( ".."))) )
                      continue;
       
                  // Формруем полный путь к файлу/каталогу
                  stPath.replace( stPath.end() - tReplaceLen, stPath.end(), fd.cFileName);
                  tReplaceLen = _tcslen( fd.cFileName); // Прикапываем для следующего replace
       
                  if( fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                      fRet = RemoveDir( stPath.c_str()); // Удаляем все потроха найденного каталога
                  else
                  {
                      // Просто удаляем найденный файл
                      if( fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
                          SetFileAttributes( stPath.c_str(), FILE_ATTRIBUTE_NORMAL);
                      fRet = DeleteFile( stPath.c_str());
                  }
       
              } while( fRet && FindNextFile( hFind, &fd));
              FindClose( hFind);
       
              // Заключительный момент - удалить пустой каталог...
              if( fRet) fRet = RemoveDirectory( szDir);
          }
          return fRet;
      }
      Че-то понамешано, STL, CRT, WinAPI... ;)
        Цитата Uncle_Bob @
        Че-то понамешано, STL, CRT, WinAPI...

        stl - для того, чтоб не вляпатся в MAX_PATH. Попробуй создать в тотале путь более 260 символов и скопировать что-нить в эту диру...
        Можно канечна обойтись и без stl, но зачем мудрить? ;)
        crt - ну, можно убрать сравнение строк и написать условие проверки на два символа.
        апи - ммм, предлагаешь на мфс заменить? :lol:
          ЗЫ. Кстати, эти пережитки с MAX_PATH могут к таким глюкам приводить. Я када писал свой плаг к тоталу, не раз попадал на это ограничение. Писал Гислеру, но он пока тока обещает увеличить свои буффера :(
            Да я не против, просто лично по мне либо одно, либо другое, либо третье ;)

            STL+API, CRT+API, MFC-only, WinAPI-only что-нить в этом роде :)
              Да я понимаю что не против :)
              Просто, стл базируется на црт, т.ч. связка STL+API-CRT не осуществима в принципе. Оставлять только апи - это значит ручками мараться со стековой/свободной памятью.
              Если используемые возможности облегчают написание кода и его понимание, то такое использование должно только приветствоваться.
                Удаление директории

                ExpandedWrap disabled
                  #include "shellapi.h"
                  #pragma comment( lib, "shell32.lib" ) // добавить shell32.lib
                   
                  // вариант для Unicode
                  int Remove_dirW(LPCWSTR pPath)
                  {
                    SHFILEOPSTRUCTW sh;
                    ZeroMemory(&sh,sizeof(SHFILEOPSTRUCTW));
                    sh.wFunc = FO_DELETE;
                    sh.pFrom = pPath; //удаляемая директория
                    //(путь в формате Unicode, завершающийся 2-мя NULL-терминаторами...)
                    sh.fFlags = FOF_NOCONFIRMATION | FOF_SILENT;
                    return SHFileOperationW(&sh);
                  }
                   
                  // Для Ansi
                  int Remove_dirA(LPCTSTR pPath)
                  {
                    SHFILEOPSTRUCTA sh;
                    ZeroMemory(&sh,sizeof(SHFILEOPSTRUCTA));
                    sh.wFunc = FO_DELETE;
                    sh.pFrom = pPath; //удаляемая директория
                    //(путь в формате Ansi, завершающийся NULL-терминатором...)
                    sh.fFlags = FOF_NOCONFIRMATION | FOF_SILENT;
                    return SHFileOperationA(&sh);
                  }
                   
                  //Пример:
                  void primer()
                  {
                    Remove_dirW(L"WidePath\0"); // Unicode
                    Remove_dirA("AnsiPath");   // Ansi
                  }


                или
                Под VCL

                ExpandedWrap disabled
                  // полное удаление каталога при помощи рекурсивного обхода всех файлов и вложенных папок
                   
                  bool DeleteDir(AnsiString DirName)
                  {
                  TSearchRec sr;
                  if (DirName.Length())
                   {
                   if (!FindFirst(DirName+"\\*.*",faAnyFile,sr))
                   do
                    {
                    if (!(sr.Name=="." || sr.Name==".."))// это удалять не надо
                     if (((sr.Attr & faDirectory) == faDirectory ) ||
                     (sr.Attr == faDirectory))// найдена папка
                      {
                      FileSetAttr(DirName+"\\"+sr.Name, faDirectory );// сброс всяких read-only
                      DeleteDir(DirName+"\\"+sr.Name);//рекурсивно удаляем содержимое
                      RemoveDir(DirName + "\\"+sr.Name);// удаляем теперь уже пустую папку
                      }
                      else// иначе найден файл
                      {
                      FileSetAttr(DirName+"\\"+sr.Name, 0);// сброс всяких read-only
                      DeleteFile(DirName+"\\"+sr.Name);// удаляем файл
                      }
                    }
                   while (!FindNext(sr));// ищем опять, пока не найдем все
                   FindClose(sr);
                   }
                  RemoveDir(DirName);
                  return true;
                  }
                Сообщение отредактировано: mad_avenger -
                  В первую функцию BOOL RemoveDir( IN LPCTSTR szDir) неплохо бы добавить некоторые параметры и возможности, типа BOOL bForceRemoveHiddenFiles, BOOL bForceRemoveSystemFiles, BOOL bForceRemoveReadOnlyFiles. :P Думаю, значение понятно :)
                  Универсальнее было бы 8)
                  Сообщение отредактировано: MinLexx -
                    Цитата MinLexx @
                    Универсальнее было бы 8)

                    Неа, не будет. Как ты себе это представляешь? Если встретятся удалять системные, а вот скрытые при этом не трогать? Тогда и дира не удалится, т.к. останется не пустой...
                      mad_avenger, подправь свою Remove_dir. Укажи необходимые инклуды, убери билдеровский хэндл окна и подправь параметр Path, чтоб функция поддерживала уникод. Кроме этого, необходимо указать, что Path обязан завершатся двумя нуль-терминаторами. Иначе просто не будет работать...
                      По vcl-ской сказать ничего не могу, не помню я уже билдеровское :)
                        Цитата Ace @
                        Цитата MinLexx @
                        Универсальнее было бы 8)

                        Неа, не будет. Как ты себе это представляешь? Если встретятся удалять системные, а вот скрытые при этом не трогать? Тогда и дира не удалится, т.к. останется не пустой...

                        Именно, если встретятся скрытые файлы при не установленном bForceRemoveHiddenFiles или если встретятся системные при не установленном bForceRemoveSystemFiles или если встретятся рид-онли при не установленном bForceRemoveReadOnlyFiles, то возвращать FALSE и прерывать удаление каталога. Или как вариант, предварительно проверять каталог на наличие возможных таких вот ошибочных ситуаций, ничего не удаляя, и если всё ОК, то удалять всё, иначе вернуть FALSE :) Первый вариант проще, удалять, пока удаляется 8)
                          Неа. Данное творение (твои флаги) - частный случай использования. Думаю, что достаточно за базу взять исходник RemoveDir, и дописать необходимые "дополнительные" возможности...
                            Цитата Ace @
                            По vcl-ской сказать ничего не могу, не помню я уже билдеровское

                            Спасибо за коммент! Сейчас сделаю.
                            Так бы не заметил...
                              А символические ссылки приведенные куски кода корректно обрабатывают?
                                Аффтора!
                                Я юзуюсь по ХР и MFC(где-то от 99 года) . Тут слыхом не слыхивали за TSearchRec и SHFILEOPSTRUCTW. Где их можна нарыть-то? :wall:
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,1137 ]   [ 15 queries used ]   [ Generated: 1.05.24, 22:59 GMT ]