Получить размер файла через `IShellItem` - PullRequest
7 голосов
/ 15 ноября 2010

Я реализовал алгоритм обхода каталога для оболочки Windows, используя IShellItem, IShellFolder, IStorage, IStream и т. Д. Все хорошо.Я даже могу ходить в файлах расширений пространства имен оболочки (например, .zip).

Однако у меня возникают проблемы с извлечением (обычных) размеров файлов, когда файлы используются какой-либо другой программой с эксклюзивным доступом.

AFAIK, нет ничего, кроме структуры STATSTG, которая дает больше информации, чем имя файла.По сути, есть 3 способа получить STATSTG для IShellItem:

  1. Итерация с использованием IEnumSTATSTG вместо IEnumIDList.Вместо того, чтобы вызывать IShellFolder::EnumObjects(), получите IStorage для папки и вызовите IStorage::EnumElements().Теперь вы получаете STATSTG структуры напрямую.
  2. Получите IStorage для IShellItem и вызовите IStorage::Stat().
  3. Получите IStream для IShellItem и вызовите IStream::Stat().

Я бы очень хотел использовать # 1, потому что это дало бы мне всю необходимую информацию.Однако я не могу заставить его перечислять содержимое папки.Я успешно извлек IStorage для папки: он сам по себе Stat() дает мне правильное имя папки.Я успешно извлек IEnumSTATSTG, но первый вызов Next(1, &item, NULL) возвращает S_FALSE и завершает перечисление.

Я бы отказался использовать # 2, так как он все еще не так плох, но извлекает IStorage для обычных файлов на диске выдает ошибку, используя IShellItem::BindToHandler(0, BHID_Storage, ...) и IShellFolder::BindToStorage(child, ...).

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

Я немного погуглил и нашел несколько фрагментов кода, которые используют подход № 3.

Вопрос : Может кто-нибудь объяснить, как ядолжен получить файл STATSTG без использования подхода № 3?

Должен ли подход № 1 работать, или реализация IStorage для обычных папок просто не дает списков?Должен ли подход №2 работать или реализация IStorage просто не реализована для обычных файлов?

Среда : 32-разрядная версия Windows Vista Ultimate, Visual Studio 2008 Express.Используя C ++, без ATL, все пользовательские COM-оболочки (собственные, могут быть соответствующим образом изменены, если предположить, что что-то там не так).

Ответы [ 2 ]

1 голос
/ 18 февраля 2016

Даже с принятым ответом потребовалось определенное время.

Первое, что вам нужно, это ссылка Свойства Windows .Оттуда вы должны знать, что хотите войти в System.Size .Оттуда вы получите две важные части информации:

System.Size

Размер файловой системы, предоставленный системой, в байтах.

shellPKey = PKEY_Size
typeInfo
type = UInt64

Зная, что это UInt64, вы можете затемполучить интерфейс IShellItem2, чтобы использовать один из многих методов получения свойств:

//Get the IShellItem2 interface out of the IShellItem object
IShellItem2 si2 = shellItem as IShellItem2;

//Get the file fize (in bytes)
UInt64 fileSize;
si2.GetUInt64(PKEY_Size, ref fileSize);
1 голос
/ 15 ноября 2010

Пробовали ли вы получить интерфейс IShellItem2, а затем запрашивать значение свойства PKEY_Size?

...