通过`IShellItem`获取文件的大小
我使用 IShellItem
、IShellFolder
、IStorage
、IStream
等为 Windows Shell 实现了目录遍历算法一切都很好。我什至可以走进 shell 命名空间扩展(例如 .zip
)文件。
但是,当其他具有独占访问权限的程序使用文件时,我在提取(常规)文件大小时遇到问题。
AFAIK,除了 STATSTG 结构之外什么也没有,它提供了比文件名更多的信息。基本上有 3 种方法可以获取 IShellItem
的 STATSTG
:
- 使用
IEnumSTATSTG
而不是IEnumIDList
进行迭代。获取文件夹的IStorage
并调用IStorage::EnumElements()
,而不是调用IShellFolder::EnumObjects()
。您现在可以直接获取STATSTG
结构。 - 获取
IShellItem
的IStorage
并调用IStorage::Stat()
。 - 获取
IShellItem
的IStream
并调用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
:
- Iterate using
IEnumSTATSTG
instead ofIEnumIDList
. Instead of invokingIShellFolder::EnumObjects()
, get theIStorage
for the folder and invokeIStorage::EnumElements()
. You now getSTATSTG
structures directly. - Get the
IStorage
for theIShellItem
and invokeIStorage::Stat()
. - Get the
IStream
for theIShellItem
and invokeIStream::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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您是否尝试过获取 IShellItem2 接口,然后查询 PKEY_Size 属性的值?
Have you tried getting hold of the IShellItem2 interface, and then querying for the value of the PKEY_Size property?
即使答案已被接受,仍需要做一些事情。
您需要的第一件事是 Windows 属性参考。从那里你必须知道你想要进入 系统大小。从那里您可以获得两条重要信息:
知道它是
UInt64
后,您就可以获取IShellItem2
接口,以便使用多种属性获取方法之一: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:
Knowing that it's a
UInt64
, you can then get ahold of theIShellItem2
interface, in order to use one of the many property-getting methods: