Как я могу посмотреть каталог с помощью FileSystemWatcher и при этом разрешить его удаление должным образом? - PullRequest
2 голосов
/ 08 августа 2010

Рассмотрим этот код:

string dir = Environment.CurrentDirectory + @"\a";
Directory.CreateDirectory(dir);
FileSystemWatcher watcher = new FileSystemWatcher(dir);
watcher.IncludeSubdirectories = false;
watcher.EnableRaisingEvents = true;
Console.WriteLine("Deleting " + dir);
Directory.Delete(dir, true);
if (Directory.Exists(dir))
{
    Console.WriteLine("Getting dirs of " + dir);
    Directory.GetDirectories(dir);
}
Console.ReadLine();

Интересно, что это создает исключение UnauthorizedAccessException для Directory.GetDirectories(dir).

Удаление просматриваемого каталога возвращается без ошибок, но Directory.Exists () по-прежнему возвращает true икаталог все еще в списке.Кроме того, доступ к каталогу дает «Доступ запрещен» для любой программы.Как только приложение .NET с FileSystemWatcher завершает работу, каталог исчезает.

Как я могу просмотреть каталог, все еще позволяя его правильно удалить?

Ответы [ 4 ]

5 голосов
/ 08 августа 2010

Вы действительно удалили каталог. Но каталог не будет физически удален из файловой системы, пока последний дескриптор, ссылающийся на него, не будет закрыт. Любая попытка открыть его между ними (как вы это делали с GetDirectories) потерпит неудачу с ошибкой отказа в доступе.

Такой же механизм существует для файлов. Обзор FileShare.Delete

2 голосов
/ 08 августа 2010

Попробуйте эту строку:

 if (new DirectoryInfo(dir).Exists)

вместо:

if (Directory.Exists(dir))
1 голос
/ 27 октября 2014

К сожалению, FileSystemWatcher использует дескриптор каталога, это означает, что при удалении каталога все еще остается дескриптор каталога, помеченный как PENDING DELETE. Я попробовал несколько экспериментов, и кажется, что вы можете использовать обработчик событий Error из FileSystemWatcher, чтобы определить, когда это произойдет.

    public myClass(String dir)
    {
        mDir = dir;
        Directory.CreateDirectory(mDir);

        InitFileSystemWatcher();

        Console.WriteLine("Deleting " + mDir);
        Directory.Delete(mDir, true);
    }
    private FileSystemWatcher watcher;

    private string mDir;

    private void MyErrorHandler(object sender, FileSystemEventArgs args)
    {
        // You can try to recreate the FileSystemWatcher here
        try
        {
            mWatcher.Error -= MyErrorHandler;
            mWatcher.Dispose();
            InitFileSystemWatcher();
        }
        catch (Exception)
        {
            // a bit nasty catching Exception, but you can't do much
            // but the handle should be released now 
        }
        // you might not be able to check immediately as your old FileSystemWatcher
        // is in your current callstack, but it's a start.
    }

    private void InitFileSystemWatcher()
    {
        mWatcher = new FileSystemWatcher(mDir);
        mWatcher.IncludeSubdirectories = false;
        mWatcher.EnableRaisingEvents = true;
        mWatcher.Error += MyErrorHandler;
    }
1 голос
/ 11 июля 2012

Вы должны использовать FileSystemInfo.Refresh. После .Refresh () .Exists показывает правильный результат:

    var dir = new DirectoryInfo(path);
    // delete dir in explorer
    System.Diagnostics.Debug.Assert(dir.Exists); // true
    dir.Refresh();
    System.Diagnostics.Debug.Assert(!dir.Exists); // false
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...