Se você estiver tentando excluir o diretório recursivamente ae o diretório a\bestiver aberto no Explorer, bele será excluído, mas o erro 'diretório não está vazio' será exibido, amesmo que esteja vazio quando você olhar. O diretório atual de qualquer aplicativo (incluindo o Explorer) mantém um identificador no diretório . Quando você liga Directory.Delete(true), ele exclui de baixo para cima:, bentão a. Se bestiver aberto no Explorer, o Explorer detectará a exclusão b, alterará o diretório para cima cd ..e limpará os identificadores abertos. Como o sistema de arquivos opera de forma assíncrona, a Directory.Deleteoperação falha devido a conflitos com o Explorer.
Solução incompleta
Originalmente, publiquei a seguinte solução, com a idéia de interromper o segmento atual para permitir que o tempo do Explorer libere o identificador de diretório.
// incomplete!
try
{
Directory.Delete(path, true);
}
catch (IOException)
{
Thread.Sleep(0);
Directory.Delete(path, true);
}
Mas isso só funciona se o diretório aberto for o filho imediato do diretório que você está excluindo. Se a\b\c\destiver aberto no Explorer e você o usar a, essa técnica falhará após excluir de c.
Uma solução um pouco melhor
Esse método manipulará a exclusão de uma estrutura de diretórios profunda, mesmo que um dos diretórios de nível inferior esteja aberto no Explorer.
/// <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);
}
}
Apesar do trabalho extra de repetir por conta própria, ainda temos que lidar com o UnauthorizedAccessExceptionque pode ocorrer ao longo do caminho. Não está claro se a primeira tentativa de exclusão está abrindo caminho para a segunda, bem-sucedida, ou se é apenas o atraso de tempo introduzido ao lançar / capturar uma exceção que permite ao sistema de arquivos recuperar o atraso.
Você pode reduzir o número de exceções lançadas e capturadas em condições típicas adicionando uma Thread.Sleep(0)no início do trybloco. Além disso, existe o risco de que, sob carga pesada do sistema, você possa passar pelas Directory.Deletetentativas e falhar. Considere esta solução como um ponto de partida para uma exclusão recursiva mais robusta.
Resposta geral
Esta solução aborda apenas as peculiaridades da interação com o Windows Explorer. Se você deseja uma operação de exclusão sólida, lembre-se de que qualquer coisa (antivírus, qualquer que seja) pode ter um identificador aberto para o que você está tentando excluir, a qualquer momento. Então você tem que tentar novamente mais tarde. Quanto mais tarde e quantas vezes você tenta depende de quão importante é que o objeto seja excluído. Como o MSDN indica ,
O código robusto de iteração de arquivo deve levar em consideração muitas complexidades do sistema de arquivos.
Essa declaração inocente, fornecida apenas com um link para a documentação de referência do NTFS, deve fazer você se arrepiar.
( Edit : Muita. Esta resposta originalmente tinha apenas a primeira solução incompleta.)