通过`IShellItem`获取文件的大小

发布于 2024-10-02 10:10:39 字数 1618 浏览 7 评论 0原文

我使用 IShellItemIShellFolderIStorageIStream 等为 Windows Shell 实现了目录遍历算法一切都很好。我什至可以走进 shell 命名空间扩展(例如 .zip)文件。

但是,当其他具有独占访问权限的程序使用文件时,我在提取(常规)文件大小时遇到​​问题。

AFAIK,除了 STATSTG 结构之外什么也没有,它提供了比文件名更多的信息。基本上有 3 种方法可以获取 IShellItemSTATSTG

  1. 使用 IEnumSTATSTG 而不是 IEnumIDList 进行迭代。获取文件夹的 IStorage 并调用 IStorage::EnumElements(),而不是调用 IShellFolder::EnumObjects()。您现在可以直接获取 STATSTG 结构。
  2. 获取 IShellItemIStorage 并调用 IStorage::Stat()
  3. 获取 IShellItemIStream 并调用 IStream::Stat()

我真的很想使用#1,因为它可以为我提供所需的所有信息。但是,我无法让它枚举文件夹内容。我成功提取了该文件夹的 IStorage:它自己的 Stat() 为我提供了正确的文件夹名称。我成功提取了 IEnumSTATSTG,但第一次调用 Next(1, &item, NULL) 返回 S_FALSE 并终止枚举。

我会回退到使用 #2,因为它仍然不是那么糟糕,但是使用 IShellItem::BindToHandler(0, BHID_Storage, ..) 提取常规磁盘文件的 IStorage 会产生错误。 .)IShellFolder::BindToStorage(child, ...)

我最终尝试了#3,尽管它看起来似乎是错误的,并且只要文件不被另一个程序以独占访问方式使用,它就会成功。

我用 google 搜索了一下,发现了几个使用方法 #3 的代码片段。

问题:谁能解释一下我应该如何在不使用方法 #3 的情况下获取文件的 STATSTG

方法 #1 应该有效吗?还是常规文件夹的 IStorage 实现根本不会生成列表?方法 #2 应该有效吗?还是 IStorage 实现根本没有针对常规文件实现?

环境:Windows Vista Ultimate 32 位、Visual Studio 2008 Express。使用 C++,无 ATL,所有自定义 COM 包装器(内部,假设有问题,可以进行适当修改)。

I've implemented a directory walking algorithm for the Windows Shell using IShellItem, IShellFolder, IStorage, IStream, etc. All is well and good. I can even walk inside shell namespace extensions (e.g. .zip) files.

However, I have problems extracting (regular) file sizes when files are being used by some other program with exclusive access.

AFAIK, there is nothing but the STATSTG structure that gives more information than the file's name. There are essentially 3 ways to get a hold of a STATSTG for a IShellItem:

  1. Iterate using IEnumSTATSTG instead of IEnumIDList. Instead of invoking IShellFolder::EnumObjects(), get the IStorage for the folder and invoke IStorage::EnumElements(). You now get STATSTG structures directly.
  2. Get the IStorage for the IShellItem and invoke IStorage::Stat().
  3. Get the IStream for the IShellItem and invoke IStream::Stat().

I would really like to use #1 because it would give me all the information I need. However, I cannot get it to enumerate folder contents. I successfully extract the IStorage for the folder: it's own Stat() gives me the proper folder name. I successfully extract the IEnumSTATSTG, but the first call to Next(1, &item, NULL) returns S_FALSE and terminates the enumeration.

I would fallback to use #2 as it is still not so bad, but extracting the IStorage for regular disk files produces an error using both of IShellItem::BindToHandler(0, BHID_Storage, ...) and IShellFolder::BindToStorage(child, ...).

I finally tried #3 although it just plains seems wrong and it succeeds as long as files are not being used with exclusive access by another program.

I've googled around a bit and found several code snippets that use approach #3.

Question: Can anyone explain how I'm supposed to get the file's STATSTG without using approach #3?

Should approach #1 work, or does the IStorage implementation for regular folders simply not produce listings? Should approach #2 work or is the IStorage implementation simply not implemented for regular files?

Environment: Windows Vista Ultimate 32-bit, Visual Studio 2008 Express. Using C++, no ATL, all custom COM wrappers (in-house, may be suitably modified assuming somwthing is wrong there).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一页 2024-10-09 10:10:39

您是否尝试过获取 IShellItem2 接口,然后查询 PKEY_Size 属性的值?

Have you tried getting hold of the IShellItem2 interface, and then querying for the value of the PKEY_Size property?

安人多梦 2024-10-09 10:10:39

即使答案已被接受,仍需要做一些事情。

您需要的第一件事是 Windows 属性参考。从那里你必须知道你想要进入 系统大小。从那里您可以获得两条重要信息:

系统大小

系统提供的项目文件系统大小(以字节为单位)。

shellPKey = PKEY_Size
类型信息
      类型 = 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);

Even with the accepted answer, it took some doing.

The first thing you need is the Windows Properties reference. From there you have to know that you want to go into System.Size. From there you get the two important pieces of information:

System.Size

The system-provided file system size of the item, in bytes.

shellPKey = PKEY_Size
typeInfo
       type = UInt64

Knowing that it's a UInt64, you can then get ahold of the IShellItem2 interface, in order to use one of the many property-getting methods:

//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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文