Почему FileSystemWatcher никогда не запускается при изменении открытого файла базы данных BDE / Paradox?

У меня есть старое родное приложение, написанное на Borland Delphi:

введите описание изображения здесь

Приложение взаимодействует со специальным оборудованием и создает / сохраняет свои данные в базе данных BDE / Borland Paradox в .db файле. Я не являюсь автором этого приложения, и компании, которая его создала, давно нет.

Мне нужно добавить в это приложение некоторые настраиваемые функции, а именно, чтобы иметь возможность читать базу данных при возникновении определенного события, связанного с оборудованием. Я нашел старую библиотеку C, которая позволяет мне читать файл paradox .db. Итак, эта часть закрыта.

Сейчас я пытаюсь найти способ отследить момент записи этим приложением в свой .db файл. Поэтому я решил попробовать в своем тестовом приложении следующее:

static void Main(string[] args)
{
    string path = "C:\\Program Files\\Company Name\\logfile.db";

    string strDirName = Path.GetDirectoryName(path);
    string strFileName = Path.GetFileName(path);

    FileSystemWatcher watcher = new FileSystemWatcher();
    watcher.Path = strDirName;

    watcher.NotifyFilter = NotifyFilters.Attributes |
        NotifyFilters.CreationTime | NotifyFilters.FileName | NotifyFilters.LastAccess |
        NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;

    watcher.Filter = strFileName;   // "*.db";

    watcher.IncludeSubdirectories = false;

    watcher.Changed += new FileSystemEventHandler(OnChanged);
    watcher.Created += new FileSystemEventHandler(OnChanged);
    watcher.Deleted += new FileSystemEventHandler(OnChanged);
    watcher.Renamed += new RenamedEventHandler(OnRenamed);
    watcher.Error += new ErrorEventHandler(OnError); 

    watcher.EnableRaisingEvents = true;

    Console.WriteLine("Starting the watch...");
    Console.WriteLine("Folder: " + watcher.Path);
    Console.WriteLine("File: " + watcher.Filter);

    while (true)
    {
        watcher.WaitForChanged(WatcherChangeTypes.All);
        Console.WriteLine("-next-");
    }
}

private static void OnChanged(object source, FileSystemEventArgs e)
{
    Console.WriteLine("-\"" + e.FullPath + "\", type=" + e.ChangeType + ", time=" + DateTime.Now);
}

private static void OnRenamed(object source, RenamedEventArgs e)
{
    Console.WriteLine("-\"{0}\" renamed to \"{1}\"", e.OldFullPath, e.FullPath);
}

private static void OnError(object source, ErrorEventArgs e)
{
    Console.WriteLine("#error: \"" + e.ToString() + "\", time=" + DateTime.Now);
}

Проблема в том, что он не видит никаких изменений в базе данных.

Если я протестирую его с файлом .txt, открыв его в Блокноте, а затем сохранив с некоторыми изменениями, он будет работать нормально. Но не с приложением, которое мне нужно.

Вот откуда я знаю, что это не работает:

  • Данное приложение уже запущено.

  • Я запускаю свое приложение рядом с ним. Он не показывает ошибок или исключений. Итак, я знаю, что моя функция watcher.WaitForChanged началась.

  • Я жду, пока аппаратное событие не будет зарегистрировано в рассматриваемом приложении.

  • Мое тестовое приложение не видит изменений.

  • Затем я копирую файл logfile.db, пока приложение и мое тестовое приложение все еще работают, а затем открываю его на своем ноутбуке с помощью средства просмотра Paradox DB. И он показывает новую запись в базе данных.

Так почему же FileSystemWatcher не улавливает, что logfile.db файл изменяется?

PS. Все это я делаю на 64-битной версии Windows 7 Pro.


person c00000fd    schedule 31.05.2018    source источник
comment
Это может иметь отношение к вам: stackoverflow.com/questions/3540801/   -  person Sam Axe    schedule 31.05.2018
comment
изменяется ли LastWrite в файле?   -  person TheGeneral    schedule 31.05.2018
comment
@SamAxe: Хм. Интересный. Я нашел это и это тоже. Мне нужно это проверить. Я не уверен, что предлагается решение? Надо тогда по таймеру диск промывать, что ли?   -  person c00000fd    schedule 31.05.2018
comment
Записи каталога гарантированно обновляются только при закрытии дескриптора. FileSystemWatcher ищет изменения записи в каталоге.   -  person Raymond Chen    schedule 31.05.2018
comment
@RaymondChen: Тогда какие у меня другие варианты отслеживания изменений в этом случае? (Мне не хотелось бы просто читать / опрашивать этот файл базы данных на повторяющемся таймере.)   -  person c00000fd    schedule 31.05.2018
comment
Мне не известно о каких-либо событиях, связанных с отдельными записями. Я думаю, вы могли бы написать драйвер фильтра, но это довольно тяжелый молоток.   -  person Raymond Chen    schedule 01.06.2018
comment
Вы можете открыть файл и закрыть его. Это перенесет время последнего изменения в каталог . Это все еще опрос, но работы меньше, чем анализ всего файла.   -  person Raymond Chen    schedule 11.06.2018
comment
@RaymondChen: Спасибо за попытку помочь. Я прочитал вашу статью и попытался вызвать CreateFileW и CloseHandle в файле, который отслеживается на предмет изменений из рабочего потока в моем процессе. К сожалению, в данном случае это ничего не изменило. Изменение в этом файле было обнаружено только тогда, когда я закрыл его в программе просмотра Paradox DB. Я также пытаюсь открыть том, где находился файл, и очистить его (например, было предлагается здесь), но это тоже не помогло :(   -  person c00000fd    schedule 12.06.2018
comment
Крысы. Возможно, они обновляют файл с помощью сопоставления файлов с отображением в памяти (что не влияет на последнее изменение).   -  person Raymond Chen    schedule 12.06.2018
comment
@RaymondChen: Я только что понял, что мне нужно было попробовать procmon на нем. Вот снимок экрана с результатом. Однако у меня странное поведение. Всякий раз, когда происходит событие, которое я хочу перехватить, он открывает этот logbase.db файл несколько раз, а затем закрывает его. Так что, черт возьми, я позволил своему тестирующему приложению немного поработать само по себе (с вашим предложением открыть и закрыть файл logbase.db из рабочего потока). К моему удивлению, когда я проверил позже, я понял, что оно поймал некоторые события. Я не уверен, почему?   -  person c00000fd    schedule 12.06.2018
comment
Рабочий поток в моем тестовом приложении запускается каждую секунду (он открывает и немедленно закрывает файл logbase.db). Я заметил, что всякий раз, когда я получаю сразу несколько аппаратных событий / входов в систему (4 или 5 подряд), которые генерируют повторяющиеся события записи к отслеживаемому файлу FileSystemWatcher, кажется, улавливает их (вместе с методом вашего рабочего потока). Но не отдельные события.   -  person c00000fd    schedule 12.06.2018
comment
Извините моя ошибка. Размер файла в записи каталога обновляется путем открытия / закрытия файла, а временные метки - нет.   -  person Raymond Chen    schedule 12.06.2018


Ответы (1)


BDE - это странная и неприятная программа для работы. Я не удивлен, что, хотя FileSystemWatcher не видит никаких изменений, копирование logfile.db действительно показывает изменения.

BDE выполняет кэширование записи и по умолчанию включено. Чтобы выключить его, попробуйте один из следующих способов:

  1. Используйте апплет администратора BDE, чтобы изменить файл IDAPI32.CNF или IDAPI32.CFG, установив для LOCAL SHARE значение TRUE.

Or,

  1. Измените реестр для машины, на которой работает BDE: [HKEY_LOCAL_MACHINE \ SOFTWARE \ Borland \ Database Engine \ Settings \ SYSTEM \ INIT] LOCAL SHARE = ​​TRUE
person Chris R. Timmons    schedule 31.05.2018
comment
Это варианты 1 и 2 И или ИЛИ? Я не думаю, что знаю, что такое административный апплет BDE. Лучше попробую сделать это в реестре. Хотя мне бы очень хотелось решить эту проблему без внесения каких-либо изменений в целевое приложение / среду. - person c00000fd; 31.05.2018
comment
Спасибо за разъяснение. Я попробую завтра и доложу. Не хочу испортить это оборудование так поздно ночью :) - person c00000fd; 31.05.2018
comment
Крис, забыл обновить этот пост. Я проверил установку BDE, и значение LOCAL SHARE в реестре уже было установлено на TRUE. - person c00000fd; 12.06.2018