Как создать “Массив IDList Shell” для поддержки перетаскивания виртуальных файлов от C# до Windows Explorer?

Я начал пытаться реализовать перетаскивание виртуальных файлов (из приложения C# 4/WPF) с этим codeproject учебным руководством. После пребывания в течение некоторого времени, пытаясь выяснить ошибку DV_E_FORMATETC, я выяснил, что должен поддерживать "формат данных" Массива IDList Shell. Но, кажется, существует рядом с нулевой документацией относительно того, что на самом деле делает этот формат.

После некоторого поиска я нашел эту страницу на усовершенствованной передаче данных, которая сказала, что Массив IDList Shell был указателем на структуру CIDA. Эта структура CIDA затем содержит количество PIDLs и список смещений им. Таким образом что, черт возьми, PIDL? Еще после некоторого поиска этот вид страницы подразумевает, что это - указатель на ITEMIDLIST, который сам содержит единственного участника, который является списком SHITEMIDs.

Я сделал еще некоторое чтение, я все еще не могу сказать то, для чего несколько PIDLs, но существует один SHITEMID для каждого "уровня" в пути. По крайней мере это - одна решенная тайна.

Моя следующая идея состояла в том, чтобы попытаться перетащить файл из другого приложения с виртуальными файлами (WinSCP). Я просто вернул MemoryStream для этого формата. По крайней мере, я знаю, какой класс предусмотреть вещь, но это не помогает вообще для объяснения, что вставить его. Я пытался исследовать этот MemoryStream на основе форматов в ссылках выше, но я не имел никакого успеха. Я просто возвратил данные мусора, и одно из 'cb' полей сказало мне, что было 18 000 байтов длиной, когда целый поток составлял только 539 байтов.

Кроме того, на дополнительные материалы для чтения, эта страница, кажется, подразумевает, что данные, содержавшиеся в PIDL на самом деле, завершают то, чтобы быть путем, и исследование содержания упомянутого MemoryStream в Hex-редакторе привело к пути в моем локальном каталоге Temp (разделение в части, так или иначе).

Кажется, что WinSCP просто использует расширение оболочки для обработки отбрасывания на проводнике, что-то, к чему я действительно не хочу обращаться. Однако это имеет альтернативный режим, где это прерывает dragdrop, пока это не передает временной папке - это приемлемо для меня, но у меня нет самой слабой идеи, как сделать это.

Мои вопросы теперь:

  1. Кто такой допустимый "abID" участник для SHITEMID? Эти виртуальные файлы только существуют с моей программой; будет вещь они перетаскиваться для передачи "abID" назад позже, когда это выполнит GetData? Они должны быть уникальными для системы?
  2. Как я могу управлять вещью перетаскивания abort-and-redo-later, которую делает WinSCP?
  3. Если бы я должен реализовать расширение оболочки для этого, как я даже пошел бы об этом? Я уверен, что могу легко найти объяснения теории расширения оболочки, но как я поддерживал бы пользовательский PIDLs или безотносительно?

Любая справка или даже связывается, которые объясняют, что я должен делать, значительно ценился бы.

Править: Таким образом, вот то, как я на самом деле сделал это в конце:

Я фрагментировал большую часть кода из учебного руководства CodeProject выше, сохранив функции для создания FileGroupDescriptor. Я затем повторно реализовал интерфейс.Net IDataObject (и на самом деле, я не должен был использовать интерфейс COM IDataObject вообще). Я затем вынужден синхронно загрузить файл в фоновом режиме и пасовать назад MemoryStream из GetData (). Удобно, фактическое копирование в фоновом режиме, но ожидание данных находится на переднем плане. Спасибо, проводник. Любые довольно большие файлы являются медленными, но на данный момент это "работает", который является больше, чем я могу сказать в течение прошлых нескольких недель.

Я действительно пытался передать класс PipeStream, который я использую внутренне для передач, но проводник не доволен этим:

  • Это пытается Искать, несмотря на это наличие класса CanSeek быть ложью.
  • Это игнорирует размер, который я отправляю в FileGroupDescriptor, и просто загружает то, что находится в потоке прямо сейчас.

Так, я не уверен, что идеальный случай на самом деле возможен. Однако, благодарит за всю Вашу справку. Я даю щедрость JPW, потому что его ответы в конечном счете устанавливают меня на правильном пути.

6
задан Community 23 May 2017 в 10:32
поделиться

3 ответа

Заявление об ограничении ответственности : я не являюсь экспертом ни в программировании Windows Shell, ни в программировании COM, и особенно в программировании COM с использованием .NET.

Заявление об ограничении ответственности 2 : Программирование оболочки довольно сложно, и Windows Explorer может дать сбой. (Обязательно прочтите информацию в MSDN по отладке расширений оболочки.)

Вот что я могу предоставить, чтобы ответить на ваши вопросы:

  1. Значение abID для SHITEMID определяется папкой, которая содержит соответствующий элемент. Следовательно, нет действительной или недействительной информации, поскольку эти данные относятся только к папке. Проводник Windows передает эти данные, чтобы идентифицировать конкретный элемент. abID не должен быть уникальным для системы, но он, вероятно, будет уникальным в своей папке (хотя это не гарантируется). При определенных обстоятельствах SHITEMID может сохраняться, поэтому в некоторых случаях он должен быть действительным после перезагрузки (из-за этого следует избегать ссылок на память в abID).
  2. Насколько я понимаю, IDataObject :: GetData будет вызываться только в том случае, если требуются фактические данные (и я могу ошибаться в этом).Так что все будет в порядке, если вы извлечете данные во временный файл в GetData и вернете PIDL в этот файл (см. http://support.microsoft.com/kb/132750/en-us , хотя я помню, что для этого был предложен удобный метод завещания, но не могу вспомнить его название). К сожалению, я не вижу хорошего способа удаления временного файла (в крайнем случае вы можете сделать это, когда IDataObject будет уничтожен, но это приведет к появлению временных файлов, которые больше не нужны).
  3. Вероятно, вам потребуется поддержка пользовательских PIDL (включая пользовательский диспетчер PIDL) и реализацию пользовательского IShellFolder. Однако большая часть документации по расширениям оболочки предназначена для C ++, и многие функции не очень хорошо документированы или вообще не задокументированы. Для получения дополнительной информации о PIDL я бы рекомендовал прочитать http://msdn.microsoft.com/en-us/library/cc144090.aspx . Кроме того, вам следует поискать в Интернете «Расширение пространства имен оболочки», поскольку там может быть некоторая информация по теме. Также ознакомьтесь с примерами, предоставленными Windows SDK по этой теме.

Надеюсь, некоторая информация будет вам полезна.

Изменить : Вы также можете реализовать QueryGetData и EnumerableFormatEtc соответствующим образом, чтобы указать, что ваш объект не поддерживает рассматриваемый формат. Может быть, тогда проводник Windows попробует другой формат.

Редактировать 2 : Хотя вы уже выбрали решение, вот еще немного информации о том, как перетаскивать асинхронно (для больших файлов), возможно, вы (или, по крайней мере, кто-то ищет ответ на аналогичная проблема, кто это читает) сочтут это полезным: http://msdn.microsoft.com/en-us/library/bb776904 (VS.85) .aspx # async

2
ответ дан 17 December 2019 в 04:42
поделиться

Думаю, Браузер файлов C # по адресу http://www.codeproject.com/KB/miscctrl/FileBrowser.aspx - это то, что сейчас вам больше всего поможет.

Эти статьи бесценны.

Edanmo.ShellExtensions абсолютно необходим. http://www.mvps.org/emorcillo/en/code/shell/shellextensions.shtml

Обратите внимание, что некоторые из этих COM-интерфейсов уже определены в .NET 2.0. (Я не проверял 4.0, но сомневаюсь, что Microsoft добавила дополнительную поддержку для интерфейсов Shell / COM.)

Extra Stuff

НАШЛИ ЭТО!

Полное руководство идиота по написанию расширений пространства имен - Часть I на http://www.codeproject.com/kb/shell/namespcextguide1.aspx . Это то, что вы ищете?

3
ответ дан 17 December 2019 в 04:42
поделиться

Видели ли вы эту статью? Как перетащить виртуальный файл из вашего приложения в проводник Windows Исходный код на c++, но он должен помочь вам понять, как все это работает.

0
ответ дан 17 December 2019 в 04:42
поделиться
Другие вопросы по тегам:

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