재귀 적으로 디렉토리를 삭제하려고 시도하고 탐색기에서 a
디렉토리 a\b
가 열려 b
있으면 삭제되지만 a
이동하고 볼 때 디렉토리가 비어 있어도 '디렉토리가 비어 있지 않습니다'라는 오류 가 발생합니다. 모든 응용 프로그램 (탐색기 포함)의 현재 디렉토리는 디렉토리에 대한 핸들을 유지합니다 . 당신이 호출 할 때 Directory.Delete(true)
, 그것은 아래에서 위로 삭제합니다 b
다음 a
. b
탐색기에서이 열려 있으면 탐색기에서 삭제를 감지하고 b
디렉토리를 위쪽으로 변경 cd ..
하며 열린 핸들을 정리합니다. 파일 시스템이 비동기 적으로 작동하기 때문에 Directory.Delete
탐색기와의 충돌로 인해 작업이 실패합니다.
불완전한 솔루션
필자는 탐색기 스레드가 디렉토리 핸들을 해제 할 수 있도록 현재 스레드를 중단한다는 아이디어와 함께 다음 솔루션을 게시했습니다.
// incomplete!
try
{
Directory.Delete(path, true);
}
catch (IOException)
{
Thread.Sleep(0);
Directory.Delete(path, true);
}
그러나 열린 디렉토리가 삭제하려는 디렉토리 의 바로 하위 인 경우에만 작동합니다 . 경우 a\b\c\d
탐색기에서 열려 있고이에를 사용 a
,이 기술은 삭제 한 후 실패 d
하고 c
.
다소 더 나은 솔루션
이 방법은 하위 디렉토리 중 하나가 탐색기에서 열려 있어도 깊은 디렉토리 구조의 삭제를 처리합니다.
/// <summary>
/// Depth-first recursive delete, with handling for descendant
/// directories open in Windows Explorer.
/// </summary>
public static void DeleteDirectory(string path)
{
foreach (string directory in Directory.GetDirectories(path))
{
DeleteDirectory(directory);
}
try
{
Directory.Delete(path, true);
}
catch (IOException)
{
Directory.Delete(path, true);
}
catch (UnauthorizedAccessException)
{
Directory.Delete(path, true);
}
}
우리 자신의 재발의 추가 작업에도 불구하고, 우리는 여전히UnauthorizedAccessException
길을 따라 발생할 수있는 것을 처리해야 합니다. 첫 번째 삭제 시도가 두 번째, 성공한 시도를위한 길을 닦고 있는지 또는 파일 시스템이 따라 올 수있는 예외를 던지거나 잡는 데서 발생하는 타이밍 지연인지는 확실하지 않습니다.
블록 Thread.Sleep(0)
의 시작 부분에 a 를 추가하여 일반적인 조건에서 발생하고 포착되는 예외 수를 줄일 수 있습니다 try
. 또한 시스템로드가 많은 경우 두 가지 Directory.Delete
시도 를 모두 수행 하여 실패 할 수있는 위험이 있습니다. 이 솔루션을보다 강력한 재귀 삭제의 시작점으로 고려하십시오.
일반적인 답변
이 솔루션은 Windows 탐색기와 상호 작용하는 특성 만 해결합니다. 견고한 삭제 작업을 원할 경우, 무엇이든 (바이러스 스캐너 등) 언제라도 삭제하려는 항목에 대해 열린 핸들을 가질 수 있다는 점을 명심해야합니다. 따라서 나중에 다시 시도해야합니다. 나중에 얼마나 많이 시도하고 몇 번 시도하는지는 개체를 삭제하는 것이 얼마나 중요한지에 달려 있습니다. 으로 MSDN을 나타냅니다 ,
강력한 파일 반복 코드는 파일 시스템의 많은 복잡성을 고려해야합니다.
NTFS 참조 문서에 대한 링크 만 제공되는이 무고한 진술은 머리카락을 돋보이게해야합니다.
( 편집 : 많이.이 답변은 원래 첫 번째, 불완전한 솔루션 만 가지고있었습니다.)