Вопрос по c#, filesystemwatcher – Обнаружение перемещенных файлов с помощью FileSystemWatcher

18

Я понимаю, что FileSystemWatcher не предоставляет событие Move, вместо этого он генерирует отдельные события Delete и Create для одного и того же файла. (FilesystemWatcher следит за исходной и целевой папками).

Однако как мы можем различить истинное перемещение файла и случайное создание файла, имя которого совпадает с именем файла, который был недавно удален?

Некоторое свойство класса FileSystemEventArgs, например "AssociatedDeleteFile» ему присваивается путь к удаленному файлу, если он является результатом перемещения, или NULL в противном случае, было бы здорово. Но, конечно, это нене существует.

Я также понимаю, что FileSystemWatcher работает на базовом уровне файловой системы, и поэтому концепция "Переехать" может иметь смысл только для приложений более высокого уровня. Но если это так, то какой алгоритм люди порекомендуют для решения этой ситуации в моем приложении?

Обновление на основе обратной связи:

Класс FileSystemWatcher, по-видимому, видит перемещение файла как просто два разных события: удаление исходного файла, за которым следует создание в новом месте.

К сожалению, нет "ссылка на сайт" между этими событиями, поэтому не очевидно, как отличить перемещение файла от обычного удаления или создания. На уровне ОС перемещение обрабатывается специально, вы можете перемещать, например, файл размером 1 ГБ практически мгновенно.

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

@ Авиада, да, яЯ ожидаю, что это должно быть на низком уровне. Если я перенесу файл размером 1 ГБ из одной папки на диске C в другую папку на том же диске, это происходит практически мгновенно. Я'Я предполагаю, что NTFS просто обновляет ссылку на указатель на файл в той же таблице файлов. Это'раздражает, что это неКажется, что он распространяется на FileSystemWatcher, поэтому мой вопрос. Ash
Насколько я помню, концепция Move в том же томе является низкоуровневой, начиная с NTFS в Windows. Так что она должна быть где-то там .. Aviad Ben Dov
@Aviad Be Dov: нет, восходит как минимум к DOS 5.0, возможно 4 MSalters

Ваш Ответ

5   ответов
2

Как вы уже упоминали, не существует надежного способа сделать это с классом FileSystemWatcher по умолчанию, предоставляемым C #. Вы можете применить определенные эвристики, такие как имя файла, хэши илиуникальные идентификаторы файлов сопоставить созданные и удаленные события вместе, но ни один из этих подходов не будет работать надежно. Кроме того, вы не можете легко получить хеш или идентификатор файла для файла, связанного с удаленным событием, а это означает, что вы должны сохранить эти значения в какой-либо базе данных.

Я думаю, что единственный надежный подход для обнаружения перемещений файлов - это создание собственного наблюдателя файловой системы. Поэтому вы можете использовать разные подходы. Если вы собираетесь наблюдать только изменения в файловых системах NTFS, одним из решений может быть чтение журнала изменений NTFS, как описаноВот, Какие'Приятно то, что он даже позволяет отслеживать изменения, произошедшие в то время, когда ваше приложение небегаю.

Другой подход заключается в создании драйвера минифильтра, который отслеживает операции файловой системы и направляет их в ваше приложение. Используя это, вы в основном получаете всю информацию о том, что происходит с вашими файлами, и выВы сможете получить информацию о перемещенных файлах. Недостаток этого подхода заключается в том, что вам необходимо создать отдельный драйвер, который необходимо установить в целевой системе. Однако хорошо то, что вы неНе нужно начинать с нуля, потому что я уже начал создавать что-то вроде этого:https://github.com/CenterDevice/MiniFSWatcher

Это позволяет вам просто отслеживать перемещенные файлы следующим образом:

var eventWatcher = new EventWatcher();

eventWatcher.OnRenameOrMove += (filename, oldFilename, process) =>
{
  Console.WriteLine("File " + oldFilename + " has been moved to " + filename + " by process " + process );
};

eventWatcher.Connect();
eventWatcher.WatchPath("C:\\Users\\MyUser\\*");

Тем не менее, имейте в виду, что для этого требуется код ядра, который должен быть подписан для запуска в 64-битной версии Windows (если вы этого не сделаетезапрещать проверка подписи для тестирования). На момент написания этот код также все еще находился на ранней стадии разработки, поэтому я бы хотелне использовать его в производственных системах еще. Но даже если тыЕсли вы не собираетесь его использовать, он все равно должен дать вам некоторую информацию о том, как события файловой системы могут отслеживаться в Windows.

2

рискну догадатьсяпереехать' на самом деле не существует, поэтому вына самом деле просто придется искатьудалять' а затем пометить этот файл как тот, который может бытьвозможно переехал, а затем, если вы видитеСоздайте' вскоре после этого, я полагаю, вы можете считать, что выисправить.

Есть ли у вас случайные создания файлов, влияющие на обнаружение ходов?

Имейте в виду, что вы выигралине нужно постоянно хэшировать; так что это должны быть довольно незначительные затраты. Noon Silk
Просто мысль: если тыидем по схеме хеширования, вы могли бы захватитьскопировал» файлы так же, как это. Aviad Ben Dov
@silky, эточто яЯ тоже думаю. Приложение индексирует файлы для поиска. Эти файлы могут быть вручную перемещены пользователем или просто добавлены (созданы) в дерево папок. Также ничто не мешает пользователю создать файл с точно таким же именем, но в разных просматриваемых папках. Ash
Хорошо, тогда я могу также рассмотреть схему хеширования. Таким образом, если вы заметили новый файл с тем же именем; Вы можете тривиально сравнивать размеры, а если размеры одинаковы, вычислять хэши и сравнивать. Это позволит вам узнать в разумной степени (достаточно разумно, учитывая индексацию, потому что если это 'с таким же содержанием, тогда хорошов принципе, хорошо, чтобы рассмотреть этопереехал» :П Noon Silk
Спасибоименно то, что я планирую сделать. Однако было бы удобно, чтобы FileSystemWatcher сообщал об этом, да ладно. Некоторые файлы могут иметь большой размер (>50 МБ), так что это сэкономило бы, делая вычисления хеша. Возможно, мне придется взглянуть на какой-то CRC, так как я считаю, что это может быть быстрее, чем хеширование Ash
2

Возможно, стоит попробовать события OnChanged и / или OnRenamed, упомянутые вдокументация.

@andymeadows, при перемещении файла создается событие Delete для исходного файла и Create для того же файла в новом месте. Я неНе вижу никаких Измененных и Переименованных событий. Ash
Это's приложение индексации поиска, которое, например, может наблюдать за пользователями "Мои документы" дерево папок для всех файлов DOC. Пользователь может вручную перемещать файлы в этом дереве или перемещать файлы в это дерево и из него. Они также могут просто удалить файлы, конечно. Различие между этими сценариями было бы полезно, чтобы избежать ненужной переиндексации файлов. Ash
Может использовать комбинацию размера файла и даты создания, чтобы сгенерировать хеш для документов, так как имя может измениться. Это быбыть по-настоящему уникальным, и вам придется расширять его в зависимости от прогнозируемого использования. Я'я уверен, что естьдругие мета, которые вы можете объединить, чтобы создать уникальный ключ. Я просто нажал вниз, и это соответствует тому, что сказал шелковистый человек. Вы'Вам придется наблюдать за обоими событиями и найти некоторые уникальные значения для вашего хэша. andymeadows
Что вы пытаетесь сделать, чтобы гарантировать ввод или перемещение файла для обработки в двух разных местах? Я бы обычно перемещал файлы с ввода -> обработка -> обработан / ошибка и не решаюсь дать больше советов без понимания, почему ваш дизайн требует этого. andymeadows
Весь смысл обнаружения перемещения состоит в том, чтобы избежать повторного выполнения дорогостоящих операций, таких как индексация и хеширование. Суть в том, чтобы найти способ узнать, что файл перемещен, без повторного вычисления хэша, поэтому хранение хэша не имеет смысла, потому что вы 'помещаем корзину перед лошадью ... то есть вычисляем хеш нового файла, чтобы определить его 'один и тот же файл ... против зная этоодин и тот же файл, так что вы ненужно пересчитать хеш. Triynko
3

Насколько я понимаю,Renamed событие для перемещения файлов ...?

Моя ошибка - в документах специально сказано, что рассматриваются только файлы внутри перемещенной папки "переименовал» в операции вырезания и вставки:

Операционная система и объект FileSystemWatcher интерпретируют действие вырезания и вставки или действие перемещения как действие переименования для папки и ее содержимого. Если вы вырезаете и вставляете папку с файлами в просматриваемую папку, объект FileSystemWatcher сообщает только о новой папке, но не о ее содержимом, потому что они по существу только переименовываются.

Это также говорит о перемещении файлов:

Обычные операции файловой системы могут вызывать более одного события. Например, когда файл перемещается из одного каталога в другой, могут возникнуть несколько событий OnChanged и некоторые события OnCreated и OnDeleted. Перемещение файла - это сложная операция, которая состоит из нескольких простых операций, поэтому вызывает несколько событий.

это верно только для папок (согласно документации) Nader Shirazie
В документах конкретно сказано "файл или каталог "... Может я'я что-то упустил? Aviad Ben Dov
@nader: тоже добавил его в ответ - посмотрел и нашел .. :( Aviad Ben Dov
Операционная система и объект FileSystemWatcher интерпретируют действие вырезания и вставки или действие перемещения как действие переименования для папки и ее содержимого »., Это под "Копирование и перемещение папок » раздел. Дон»t, где переименовано относится к файлам. Кто-нибудь проверял это? Nader Shirazie
11

Согласнодокументы:

Обычные операции файловой системы могут вызывать более одного события. Например, когда файл перемещается из одного каталога в другой, могут возникнуть несколько событий OnChanged и некоторые события OnCreated и OnDeleted. Перемещение файла - это сложная операция, которая состоит из нескольких простых операций, поэтому вызывает несколько событий.

Так что если выпытаясь быть очень осторожным в обнаружении движений, и наличие одного и того же пути недостаточно хорошо, вам придется использовать какую-то эвристику. Например, создать "отпечатков пальцев» используя имя файла, размер, время последнего изменения и т. д. для файлов в исходной папке. Когда вы видите какое-либо событие, которое может сигнализировать о движении, отметьте "отпечатков пальцев» против нового файла.

@ash, нп, рад помочь Nader Shirazie
@nader, да, я могу хранить хэш для каждого файла, поэтому я могу использовать его в качестве отпечатка пальца. Таким образом, в моей рабочей очереди я могу проверить событие Delete и дождаться последующего события Create в том же файле (гарантировано), но как долго ждать это последующее событие Create, прежде чем рассматривать его как простое событие Delete? Это'Сложнее, чем ожидалось. Ash
@nader, @silky, спасибо за ваш отзыв. Да я'Я думаю, мне просто нужно провести тестирование. Вы'Мы также помогли мне подтвердить мой подход к этому. Ash
@ash, You 'Возможно, мне понадобится протестировать несколько различных сценариев, чтобы найти хороший ответ на этот вопрос. Как говорит шелковистый, на диске очень быстро (изменить некоторые метаданные о файле / папке), в то время как между дисками требуется копирование (что может занять время). Вопрос в том, происходит ли удаление немедленно (как только вы сделаете перемещение) или только после того, как произойдет копирование (в последнем случае удаление / создание, вероятно, не происходит)так далеко друг от друга, в первомпридется подождать довольно долго). Nader Shirazie
Можете ли вы получить размер файла и диска в событии удаления? Если это так, вы можете использовать эту информацию для принятия решения. Ход в том же приводе, как правило, так же хорош, как и немедленный. Так что, может быть, 5 секунд. Но на другой диск, этоЭто так же медленно, как копирование, чтобы решить на основе размера. Не просто ясно, но возможно весело :) Noon Silk

Похожие вопросы