Drag&Drop vs NTFS Stream
От: DovydenkoAndrej  
Дата: 05.03.09 10:16
Оценка:
Привет,

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

Drag&Drop реализовал через пару CF_FILEDESCRIPTOR&CF_FILECONTENTS, таким образом я отдаю эксплореру экземпляр IStream из которого тот берёт содержимое файла. Файл создаёться полностью валидный, за исключением отсутсвия в нём альтернативного потока. Точный путь до созданного файла остаётся неизвестным, и поэтому, дописать данные после завершения операции нельзя.

Создать временный файл с потоком и отдавать его эксплореру через CF_HDROP тоже нельзя, файл скачиваеться с удалённого и весьма медленного сервера. Для CF_HDROP операция скачивания должна быть выполнена до начала сброса, чтоб отдать системе имя временноно файла(опятьже не ясно когда его можно будет удалять). С другой стороны пара CF_FILEDESCRIPTOR&CF_FILECONTENTS в этом отношении очень удобна, операция скачивания откладываеться на самый последний момент.

Посоветуйте, как мне сделать создание альтернативного потока NTFS в файле созданном через Drag&Drop?

Андрей
ntfs stream drag&drop shell shellextension istream idataobject
Re: Drag&Drop vs NTFS Stream
От: Nikolaz Германия www.nikeware.com
Дата: 05.03.09 22:54
Оценка:
Здравствуйте, DovydenkoAndrej, Вы писали:
DA>Посоветуйте, как мне сделать создание альтернативного потока NTFS в файле созданном через Drag&Drop?
Посоветовать увы не смогу ничего , но подтвердить эту проблему могу.
Я столкнулся с тем, что например апишный MoveFile() не переносит NTFS потоки, а CopyFile() отрабатывает корректно.
Увы, в вашей ситуации, похоже код, который создает новый файл, производит копирование без учета наличия NTFS потоков в исходном файле.
Впрочем так поступает наверное 99,9% всех программ.

Николай
Re[2]: Drag&Drop vs NTFS Stream
От: Nikolaz Германия www.nikeware.com
Дата: 06.03.09 08:33
Оценка:
Здравствуйте, 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 как некое средство хранения своих данных.

Это тема для отдельно беседы, сейчас протестирую свою идею и отпишусь по этому поводу

Андрей
Re[4]: Drag&Drop vs NTFS Stream
От: DovydenkoAndrej  
Дата: 06.03.09 10:48
Оценка:
Здравствуйте, Аноним, Вы писали:

А>в идеале, былобы совершенно замечательноЮ чтоб система запросила втрой IStream для альтернативного потока, на тот случай если копирование идёт на NTFS том. Кстати, меня тут идейка посетила сейчас буду проверять отпишусь. В кратце нужно при начале операции Dnd создавать список файлов содержащий не только "myfile.txt" но и "myfile.txt:my_stream"


Ничего не вышло, система проверяет существование пути и сваливается на двоеточии.

N>>Мне кажется, что вы изначально поступили неправильно, использовав альтернативные потоки NTFS как некое средство хранения своих данных.

А>Это тема для отдельно беседы, сейчас протестирую свою идею и отпишусь по этому поводу

Так вот, идёт разработка некой системы управления документами, для каждого документа нужно знать его ид в репозитории и некоторые другие данные. Они хранятсья в XML, в альтернативном потоке тогоже файла. У svn репозитория, наприме, подобные вещи храняться в скрытой папке .svn. Там обычно единица храниения это проект в котором множествой файлов и папок, тут всегда один файл — создавать для него скрытую папку или скрытый файл рядом довольно уныло. Хранить данные где-то централизованно и следить за файлами по именам — тоже глупо. Файлы всегда скачиваються из репозитория и никогда не переносяться на другие разделы (флешка фатовская например). Так что в целом решение получилось весьма удачное.
Re[5]: Drag&Drop vs NTFS Stream
От: Nikolaz Германия www.nikeware.com
Дата: 06.03.09 15:42
Оценка:
Здравствуйте, DovydenkoAndrej, Вы писали:

DA> Так что в целом решение получилось весьма удачное.

До тех пор пока я, например не взял, и не открыл этот файл в каком-нибудь простеньком редакторе, что-то там сделал и сохранил изменения
Re: Drag&Drop vs NTFS Stream
От: Vi2 Удмуртия http://www.adem.ru
Дата: 06.03.09 17:54
Оценка:
Здравствуйте, 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_HDROP
End 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.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[6]: Drag&Drop vs NTFS Stream
От: Аноним  
Дата: 07.03.09 05:04
Оценка:
Здравствуйте, Nikolaz, Вы писали:

N>Здравствуйте, DovydenkoAndrej, Вы писали:


DA>> Так что в целом решение получилось весьма удачное.

N>До тех пор пока я, например не взял, и не открыл этот файл в каком-нибудь простеньком редакторе, что-то там сделал и сохранил изменения

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


Возвращаясь к нашим баранам. Есть жуткая идея отслеживать создание нового файла в системе. Те при днд explorer создаст файл на диске с указанным мной именем, это можно отследить. Как только он будет полностью создан и закрыт, дописать в него второй поток. Сильно не хочу так делать Есть другие предложения?
Re[2]: Drag&Drop vs NTFS Stream
От: DovydenkoAndrej  
Дата: 07.03.09 05:43
Оценка:
Здравствуйте, 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.
Re[3]: Drag&Drop vs NTFS Stream
От: Vi2 Удмуртия http://www.adem.ru
Дата: 07.03.09 14:51
Оценка:
Здравствуйте, DovydenkoAndrej, Вы писали:

DA>Спасибо, действительно очень интересно, а функции xxx_OLE* какой интерфейс реализуют? Что-то я их не нашёл среди IDropSource IDataObject.


Это событийные интерфейсы контролов VB, например, CommandButton, TextBox, ListBox etc.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[7]: Drag&Drop vs NTFS Stream
От: Nikolaz Германия www.nikeware.com
Дата: 09.03.09 08:36
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Только что специально проверил, редактором был фар — всё ок поток остался на месте и ничего ему не случилось.

А фар это эталон такой?

Повторюсь еще раз — далеко не все программы знают, что такое NTFS Stream.

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

Нормальная практика, и многие программы так делают — сохранять изменения сначала в промежуточный, временный файл, и только потом удалять "старый" и переименовывать временный в постоянный. Так вот как раз при такой схеме все NTFS Streams естественно и теряются. И если программа действует по такой схеме и автор не знает о существовании NTFS Stream, то результат "на лицо", как говорится.

Еще раз — надеятся на то, что NTFS Stream в файле будет существовать "вечно", не стоит. Слишком много софта, который о факте существования NTFS Stream вообще не догадывается.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.