Пишу расширение оболчки, столкнулся со следующий проблемой, при перетаскивании объекта из моего приложения в эксплорер нужно создать файл с альтернативным потоком NTFS. В альтернативном потоке храняться метаданные, необходимые для дальнейшей работы приложения.
Drag&Drop реализовал через пару CF_FILEDESCRIPTOR&CF_FILECONTENTS, таким образом я отдаю эксплореру экземпляр IStream из которого тот берёт содержимое файла. Файл создаёться полностью валидный, за исключением отсутсвия в нём альтернативного потока. Точный путь до созданного файла остаётся неизвестным, и поэтому, дописать данные после завершения операции нельзя.
Создать временный файл с потоком и отдавать его эксплореру через CF_HDROP тоже нельзя, файл скачиваеться с удалённого и весьма медленного сервера. Для CF_HDROP операция скачивания должна быть выполнена до начала сброса, чтоб отдать системе имя временноно файла(опятьже не ясно когда его можно будет удалять). С другой стороны пара CF_FILEDESCRIPTOR&CF_FILECONTENTS в этом отношении очень удобна, операция скачивания откладываеться на самый последний момент.
Посоветуйте, как мне сделать создание альтернативного потока NTFS в файле созданном через Drag&Drop?
Здравствуйте, DovydenkoAndrej, Вы писали: DA>Посоветуйте, как мне сделать создание альтернативного потока NTFS в файле созданном через Drag&Drop?
Посоветовать увы не смогу ничего , но подтвердить эту проблему могу.
Я столкнулся с тем, что например апишный MoveFile() не переносит NTFS потоки, а CopyFile() отрабатывает корректно.
Увы, в вашей ситуации, похоже код, который создает новый файл, производит копирование без учета наличия NTFS потоков в исходном файле.
Впрочем так поступает наверное 99,9% всех программ.
Здравствуйте, DovydenkoAndrej, Вы писали: DA>Посоветуйте, как мне сделать создание альтернативного потока NTFS в файле созданном через Drag&Drop?
C утра на свежую голову подумалось следующее:
Думаю что в общем случае ответ отрицательный.
Все дело в том, что уровень IStream это более абстрактный уровень, чем файловый. На уровне системы между папкой и директорием большая разница. IStream это подложка под ваши данные, и во что реально он превратится после того же Drag&Drop, еще неизвестно. Что будет например, если у меня есть какая-нибудь виртуальная папка? Да тот же zip-файл, открытый как папка в эксплорере? Я туда могу спокойно набросать файлов. Но реально они хранятся не в каталоге, а в zip-файле! А что делать с сетевыми каталогами? А что делать с каталогами не на NTFS томах (FAT32 например)?
Мне кажется, что вы изначально поступили неправильно, использовав альтернативные потоки NTFS как некое средство хранения своих данных. Большинство программ да и сама система часто при копировании или переносе файла "забывают" скопировать потоки NTFS. Ими можно пользоваться, но только в некоторых случаях, имея ввиду именно факт их неперманентного существования. Как пример, я их использую для хранения check-суммы файла. И если вижу что она есть в потоке, создана мною и файл не менялся с момента подсчета check-суммы, то только тогда опираюсь на эту информацию в дальнейшем. Иначе считаю check-сумму заново.
Николай
Re[3]: Drag&Drop vs NTFS Stream
От:
Аноним
Дата:
06.03.09 09:31
Оценка:
Здравствуйте, Nikolaz, Вы писали:
N>Что будет например, если у меня есть какая-нибудь виртуальная папка? Да тот же zip-файл, открытый как папка в эксплорере? Я туда могу спокойно набросать файлов. Но реально они хранятся не в каталоге, а в zip-файле! А что делать с сетевыми каталогами? А что делать с каталогами не на NTFS томах (FAT32 например)?
в идеале, былобы совершенно замечательноЮ чтоб система запросила втрой IStream для альтернативного потока, на тот случай если копирование идёт на NTFS том. Кстати, меня тут идейка посетила сейчас буду проверять отпишусь. В кратце нужно при начале операции Dnd создавать список файлов содержащий не только "myfile.txt" но и "myfile.txt:my_stream"
N>Мне кажется, что вы изначально поступили неправильно, использовав альтернативные потоки NTFS как некое средство хранения своих данных.
Это тема для отдельно беседы, сейчас протестирую свою идею и отпишусь по этому поводу
Здравствуйте, Аноним, Вы писали:
А>в идеале, былобы совершенно замечательноЮ чтоб система запросила втрой IStream для альтернативного потока, на тот случай если копирование идёт на NTFS том. Кстати, меня тут идейка посетила сейчас буду проверять отпишусь. В кратце нужно при начале операции Dnd создавать список файлов содержащий не только "myfile.txt" но и "myfile.txt:my_stream"
Ничего не вышло, система проверяет существование пути и сваливается на двоеточии.
N>>Мне кажется, что вы изначально поступили неправильно, использовав альтернативные потоки NTFS как некое средство хранения своих данных. А>Это тема для отдельно беседы, сейчас протестирую свою идею и отпишусь по этому поводу
Так вот, идёт разработка некой системы управления документами, для каждого документа нужно знать его ид в репозитории и некоторые другие данные. Они хранятсья в XML, в альтернативном потоке тогоже файла. У svn репозитория, наприме, подобные вещи храняться в скрытой папке .svn. Там обычно единица храниения это проект в котором множествой файлов и папок, тут всегда один файл — создавать для него скрытую папку или скрытый файл рядом довольно уныло. Хранить данные где-то централизованно и следить за файлами по именам — тоже глупо. Файлы всегда скачиваються из репозитория и никогда не переносяться на другие разделы (флешка фатовская например). Так что в целом решение получилось весьма удачное.
Здравствуйте, DovydenkoAndrej, Вы писали:
DA> Так что в целом решение получилось весьма удачное.
До тех пор пока я, например не взял, и не открыл этот файл в каком-нибудь простеньком редакторе, что-то там сделал и сохранил изменения
Здравствуйте, DovydenkoAndrej, Вы писали:
DA>Пишу расширение оболочки, столкнулся со следующий проблемой, при перетаскивании объекта из моего приложения в эксплорер нужно создать файл с альтернативным потоком NTFS. В альтернативном потоке храняться метаданные, необходимые для дальнейшей работы приложения.
DA>Drag&Drop реализовал через пару CF_FILEDESCRIPTOR&CF_FILECONTENTS, таким образом я отдаю эксплореру экземпляр IStream из которого тот берёт содержимое файла. Файл создаёться полностью валидный, за исключением отсутсвия в нём альтернативного потока. Точный путь до созданного файла остаётся неизвестным, и поэтому, дописать данные после завершения операции нельзя.
DA>Создать временный файл с потоком и отдавать его эксплореру через CF_HDROP тоже нельзя, файл скачиваеться с удалённого и весьма медленного сервера. Для CF_HDROP операция скачивания должна быть выполнена до начала сброса, чтоб отдать системе имя временноно файла(опятьже не ясно когда его можно будет удалять). С другой стороны пара CF_FILEDESCRIPTOR&CF_FILECONTENTS в этом отношении очень удобна, операция скачивания откладываеться на самый последний момент.
DA>Посоветуйте, как мне сделать создание альтернативного потока NTFS в файле созданном через Drag&Drop?
Изучая события в VB, связанные с drag'n'drop, CF_HDROP позволяет отложенную загрузку. Другие форматы я не проверял, но думаю, что задействуется общий механизм, который не должен делать отличия в форматах. Косвенно CF_FILEDESCRIPTOR&CF_FILECONTENTS подтверждает. Что искать и где искать — не могу подсказать.
В подтверждение моих слов привожу обработчики событий начала операции drag'n'drop, запроса данных и освобождения в конце операции drag'n'drop при отработке реального drop-а. Если операции drop не было, то событие на запрос данных не приходит.
Private Sub xxxx_OLEStartDrag(Data As MSComctlLib.DataObject, AllowedEffects As Long)
AllowedEffects = (vbDropEffectMove Or vbDropEffectCopy)
...
Call Data.Clear
Call Data.SetData(, vbCFFiles) ' vbCFFiles == CF_HDROPEnd Sub
Private Sub xxxx_OLESetData(Data As MSComctlLib.DataObject, DataFormat As Integer)
If DataFormat = vbCFFiles Then' vbCFFiles == CF_HDROP
msDraggedFile = "..."Call SaveAs(msDraggedFile, ...)
Call Data.Files.Add(msDraggedFile)
End If
End Sub
Private Sub xxxx_OLECompleteDrag(Effect As Long)
If Len(msDraggedFile) <> 0 Then
Call Kill(msDraggedFile)
msDraggedFile = ""End If
...
Effect = vbDropEffectNone
End Sub
PS
MSComctlLib.DataObject — это VB-шный аналог или реализация интерфейса IDataObject.
Здравствуйте, Nikolaz, Вы писали:
N>Здравствуйте, DovydenkoAndrej, Вы писали:
DA>> Так что в целом решение получилось весьма удачное. N>До тех пор пока я, например не взял, и не открыл этот файл в каком-нибудь простеньком редакторе, что-то там сделал и сохранил изменения
Только что специально проверил, редактором был фар — всё ок поток остался на месте и ничего ему не случилось. Единственная возможность — это если не сохранить файл на том-же месте, а использовать "сохранить как". Но во первых это уже совсем другой документ, а во вторых к программам редактирования этих документов написаны плагины, которые (среди прочего функционала) отслеживают такие вещи и подкладывают обновлённые метаданные.
Возвращаясь к нашим баранам. Есть жуткая идея отслеживать создание нового файла в системе. Те при днд explorer создаст файл на диске с указанным мной именем, это можно отследить. Как только он будет полностью создан и закрыт, дописать в него второй поток. Сильно не хочу так делать Есть другие предложения?
Здравствуйте, Vi2, Вы писали:
Vi2>Изучая события в VB, связанные с drag'n'drop, CF_HDROP позволяет отложенную загрузку. Другие форматы я не проверял, но думаю, что задействуется общий механизм, который не должен делать отличия в форматах. Косвенно CF_FILEDESCRIPTOR&CF_FILECONTENTS подтверждает. Что искать и где искать — не могу подсказать.
Vi2>В подтверждение моих слов привожу обработчики событий начала операции drag'n'drop, запроса данных и освобождения в конце операции drag'n'drop при отработке реального drop-а. Если операции drop не было, то событие на запрос данных не приходит. Vi2>
Vi2>Private Sub xxxx_OLEStartDrag(Data As MSComctlLib.DataObject, AllowedEffects As Long)
Vi2>Private Sub xxxx_OLESetData(Data As MSComctlLib.DataObject, DataFormat As Integer)
Vi2>Private Sub xxxx_OLECompleteDrag(Effect As Long)
Vi2>
Спасибо, действительно очень интересно, а функции xxx_OLE* какой интерфейс реализуют? Что-то я их не нашёл среди IDropSource IDataObject.
Здравствуйте, DovydenkoAndrej, Вы писали:
DA>Спасибо, действительно очень интересно, а функции xxx_OLE* какой интерфейс реализуют? Что-то я их не нашёл среди IDropSource IDataObject.
Это событийные интерфейсы контролов VB, например, CommandButton, TextBox, ListBox etc.
Здравствуйте, Аноним, Вы писали:
А>Только что специально проверил, редактором был фар — всё ок поток остался на месте и ничего ему не случилось.
А фар это эталон такой?
Повторюсь еще раз — далеко не все программы знают, что такое NTFS Stream.
"Хорошо", если программист при сохранении изменений в уже существующий файл открыл его на запись и по новой все в него сбросил.
Но кто застрахован, что на пол-пути при сохранении у вас не произойдет что-то фатальное? Потеряете как минимум файл .
Нормальная практика, и многие программы так делают — сохранять изменения сначала в промежуточный, временный файл, и только потом удалять "старый" и переименовывать временный в постоянный. Так вот как раз при такой схеме все NTFS Streams естественно и теряются. И если программа действует по такой схеме и автор не знает о существовании NTFS Stream, то результат "на лицо", как говорится.
Еще раз — надеятся на то, что NTFS Stream в файле будет существовать "вечно", не стоит. Слишком много софта, который о факте существования NTFS Stream вообще не догадывается.