Get file size through `IShellItem`

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

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

AFAIK, there is nothing but the STATSTG structure, which gives more information than the file name. There are 3 ways to get STATSTG for IShellItem :

  • IEnumSTATSTG use IEnumSTATSTG instead of IEnumIDList . Instead of calling IShellFolder::EnumObjects() , start IStorage for the folder and call IStorage::EnumElements() . Now you get STATSTG structures.
  • Get IStorage for IShellItem and call IStorage::Stat() .
  • Get IStream for IShellItem and call IStream::Stat() .

I would really like to use # 1, because it will provide me with all the information I need. However, I cannot get it to list the contents of the folder. I successfully retrieve IStorage for the folder: it Stat() gives me the correct folder name. I successfully retrieve IEnumSTATSTG , but the first call to Next(1, &item, NULL) returns S_FALSE and completes the enumeration.

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

I finally tried # 3, although that just the pros seem to be wrong, and it succeeds until the files are used with exclusive access by another program.

I searched the language a bit and found some code snippets that use approach # 3.

Question Can anyone explain how I should get the STATSTG file without using approach # 3?

Should approach # 1 work, or is the IStorage implementation for regular folders just not creating lists? Should approach number 2 work, or is IStorage just not implemented for regular files?

Environment : Windows Vista Ultimate 32-bit version of Visual Studio 2008 Express. Using C ++, there is no ATL, all user COM wrappers (internal, can be changed accordingly if we assume that something is wrong there).

+7
c ++ windows windows-shell
source share
2 answers

Have you tried to get the IShellItem2 interface, and then request the value of the PKEY_Size property?

+1
source share

Even with the accepted answer, it took some time.

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

System.Size

The system file size of the item in bytes.

shellPKey = PKEY_Size
Typeinfo
type = UInt64

Knowing that this is a UInt64 , you can get the IShellItem2 interface to use one of the many methods of getting property:

 //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
source share

All Articles