Краткий ответ:
- Это не только для чтения, но вы не можете записать свои файлы напрямую в "исходную" файловую систему через проекцию.
WriteFileData
метод используется для заполнения файлов-заполнителей в «чистой» (проектируемой) файловой системе, поэтому он не влияет на «исходную» файловую систему.
Длинный ответ:
Как указано в комментарии @ zett42, ProjFS в основном была разработана как удаленная файловая система git. Итак, основная цель любой системы управления версиями файлов - обрабатывать несколько версий файлов. Отсюда возникает вопрос - нужно ли перезаписывать файл внутри удаленного репозитория при записи файла ProjFS? Это было бы катастрофично. При работе с git вы всегда пишете файлы локально, и они не синхронизируются, пока вы не отправите изменения в удаленный репозиторий.
При перечислении файлов ничего не записывается в локальную файловую систему. Из документации ProjFS:
Когда провайдер впервые создает корень виртуализации, он пуст
локальная система. То есть ни один из элементов в резервном хранилище данных
еще не был кэширован на диск.
Только после открытия файла ProjFS создает для него «местозаполнитель» в локальной файловой системе - я предполагаю, что это файл со специальной структурой (не реальной).
Когда открываются файлы и каталоги в корневом каталоге виртуализации,
провайдер создает заполнители на диске, а при чтении файлов
заполнители увлажняются содержимым.
Что значит "гидратированный"? Скорее всего, он представляет собой особую структуру данных, частично заполненную реальными данными. Я бы представил заполнитель как губку, частично заполненную данными.
Когда элементы открываются, ProjFS запрашивает информацию у поставщика, чтобы разрешить создание заполнителей для этих элементов в локальной файловой системе. При доступе к содержимому элемента ProjFS запрашивает его у поставщика. В результате, с точки зрения пользователя, виртуализированные файлы и каталоги выглядят аналогично обычным файлам и каталогам, которые уже находятся в локальной файловой системе.
Только после обновления файла (изменения). Это больше не заполнитель - он становится «Полный файл / каталог»:
Для файлов: содержимое файла (первичный поток данных) было изменено.
Файл больше не является кешем своего состояния в хранилище провайдера.
Файлы, которые были созданы в локальной файловой системе (т.е.
не существует в магазине провайдера вообще) также считается
полные файлы.
Для каталогов: каталоги, созданные в локальном файле
система (т.е. вообще не существует в магазине провайдера)
считается полными каталогами. Каталог, который был создан на
диск как заполнитель никогда не становится полным каталогом.
Это означает, что при первой записи заполнитель заменяется реальным файлом в локальной FS. Но как синхронизировать «удаленный» файл с измененным? (1)
Когда провайдер вызывает PrjWritePlaceholderInfo для записи
заполнитель информации, он предоставляет ContentID в VersionInfo
член аргумента placeholderInfo. Поставщик должен затем
запишите, что заполнитель для этого файла или каталога был создан в
этот взгляд.
Уведомление " Поставщик должен затем записать, что заполнитель для этого файла ". Это означает, что для последующей синхронизации файла с представлением правильного мы должны запомнить, с какой версией связан измененный файл. Представьте, что мы находимся в репозитории git и меняем ветку. В этом случае мы можем обновить один файл несколько раз в разных ветках. Теперь, почему и когда провайдер звонит PrjWritePlaceholderInfo
?
... Эти заполнители представляют состояние резервного магазина навремя они были созданы.Эти кэшированные элементы в сочетании с элементами, проецируемыми провайдером в перечислениях, составляют «представление» клиентского хранилища.Время от времени провайдер может захотеть обновить представление клиента, будь то из-за изменений в резервном хранилище или из-за явных действий, предпринятых пользователем для изменения своего представления.
Еще раз представьте себепереключение веток в git-репозитории;Вы должны обновить файл, если он отличается в другой ветке.Продолжая отвечать на вопрос (1).Imaging вы хотите сделать "толчок" из определенной ветви.Прежде всего, вы должны знать, какие файлы изменены.Если вы не записали информацию о заполнителе во время изменения файла, вы не сможете сделать это правильно (по крайней мере, для примера с git-репозиторием).
Помните, что заполнитель заменяется реальным файлом вмодификация?ProjFS имеет событие OnNotifyFileHandleClosedFileModifiedOrDeleted
.Вот подпись обратного вызова:
public void NotifyFileHandleClosedFileModifiedOrDeletedCallback(
string relativePath,
bool isDirectory,
bool isFileModified,
bool isFileDeleted,
uint triggeringProcessId,
string triggeringProcessImageFileName)
Для нашего понимания наиболее важным параметром для нас является relativePath
.Он будет содержать имя измененного файла в файловой системе «нуля» (проецируется).Здесь вы также знаете, что файл является реальным файлом (а не заполнителем) и записывается на диск (то есть вы не сможете перехватить вызов до записи файла).Теперь вы можете скопировать его в нужное место (или сделать это позже) - это зависит от ваших целей.
Отвечая на вопрос № 2, похоже, что PrjWriteFileData
используется только для заполнения "чистой" файловой системыи вы не можете использовать его для обновления «исходной» файловой системы.
Приложения:
Что касается приложений, вы все равно можете реализовать удаленную файловую систему (вместо использованияDokan), но все записи будут кэшироваться локально, а не записываться напрямую в удаленное местоположение.Пара вариантов использования:
- Распределенные файловые системы
- Online Drive Client
- Файловая система «Диспетчер» (например, вы можете записывать файлы в разныепапки в зависимости от конкретных условий)
- Система управления версиями файлов (например, вы можете сохранить разные версии одного и того же файла после изменения)
- Зеркальное отображение данных из вашего приложения в файловую систему (дляНапример, вы можете «проецировать» текстовый файл с отступами на папки, подпапки и файлы)
PS: я не знаю ни одного недокументированного API, но с моей точки зрения (соответственнос документацией) мы не можем использовать ProjFS для таких целей, как виртуальный диск или записывать файлы непосредственно в «исходную» файловую систему без предварительной записи их в «локальную» файловую систему.