Примечание: Вопрос, предложенный в качестве дубликата, обсуждает CreateFile
, ERROR_FILE_NOT_FOUND
, имея существующие ручки в файле и помещая файл для последующего удаления. Хотя это аналогичная тема, ни одна из этих проблем не относится к моему делу.FindFirstFile/FindNextFile не возвращает все файлы в папке
У меня есть следующий способ удаления каталога. Я использовал его некоторое время без проблем.
Но в последнее время я действительно выполнял свои задачи с большой задачей, удаляя каталоги и файлы по сетевому пути (только USB-накопитель, подключенный к моему маршрутизатору).
Все работает отлично, за исключением одной области, где не удаляются все файлы в каталоге, и поэтому RemoveDirectory()
не работает. (Я добавил каждый файл в список и проверил, что в список не были файлы, которые не были удалены.)
Все файлы называются очень похожими, и нет ничего необычного в отношении имени файлов, которые не были возвращены или удален. Если я снова запустил программу, она удалит оставшиеся файлы и затем будет иметь ту же ошибку немного позже в другом каталоге.
bool CBackupWorker::DeleteDirectory(LPCTSTR lpszName)
{
if (!DirectoryExists(lpszName))
{
ASSERT(false); // Unexpected
return true;
}
CFileFind find;
BOOL bContinue = find.FindFile(AppendPath(lpszName, _T("*")));
while (bContinue)
{
bContinue = find.FindNextFile();
if (find.IsDirectory())
{
if (!find.IsDots())
{
if (!DeleteDirectory(find.GetFilePath()))
return false;
}
}
else
{
if (find.IsReadOnly())
ClearReadOnlyAttribute(find);
if (!::DeleteFile(ConvertToExtendedLengthPath(find.GetFilePath())))
{
LogErrorV(::GetLastError(), _T("ERROR DELETING FILE : '%s'"), (LPCTSTR)find.GetFilePath());
return false;
}
}
}
CString sPath = ConvertToExtendedLengthPath(lpszName);
DWORD dwAttributes = ::GetFileAttributes(sPath);
if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_READONLY))
::SetFileAttributes(sPath, dwAttributes & (DWORD)~FILE_ATTRIBUTE_READONLY);
if (!::RemoveDirectory(sPath))
{
LogErrorV(::GetLastError(), _T("ERROR DELETING DIRECTORY : '%s'"), lpszName);
return false;
}
return true;
}
Несколько замечаний по коду: ConvertToExtendedLengthPath()
добавляет префикс так, что пути длиннее, чем MAX_PATH
будет разрешено; однако, хотя эти имена довольно длинные, ни один из них не превышает MAX_PATH
. (В этом случае метод просто возвращает значение ввода.)
Кроме того, я удаляю атрибут «только для чтения» для файлов и каталогов, имеющих этот атрибут. Но опять же, я подтвердил, что это не вступает в игру ни с одним из файлов, с которыми я сейчас работаю.
И, наконец, это не тот случай, когда файлы, с которыми я работаю, меняются. Я единственный, у кого есть доступ к этому внешнему диску.
Кто-нибудь видел случай, когда FindFirstFile
/FindNextFile
пропустит несколько файлов? Или когда доступ к файлам через сетевой ресурс может помешать работе этих функций?
В MSDN есть небольшое примечание, связанное с атрибутами файла, возвращаемыми FindFirstFile/FindNextFile [здесь] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa364418). Проверьте, соответствует ли это вам: Примечание. В редких случаях или в сильно загруженной системе информация атрибута файла в файловых системах NTFS может не быть актуальной во время вызова этой функции. Чтобы быть уверенным в получении текущих файловых атрибутов файловой системы NTFS, вызовите функцию GetFileInformationByHandle. – cha
Возможно, вам стоит использовать операцию 'SHFilOperation()', такую как ['RemoveDirectory()' documentation] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa365488.aspx). : "* Чтобы рекурсивно удалить файлы в каталоге, используйте функцию' SHFileOperation'. * –
Я подозреваю, что проблема заключается в том, что, удаляя файлы по мере поступления, вы меняете содержимое каталога во время сканирования. , вы могли бы сначала сохранить все имена файлов и каталогов и только затем удалить их? –