|
-
Oct 26th, 2015, 08:21 PM
#1
[VB6, Vista+] A compact function to retrieve any property by name, locally formatted
This is related to the greatly expanded property system available in Vista+, and is closely related to the more complete tour of the system in my other projects.
While this method is inefficient and shouldn't be used for large numbers of properties or large numbers of files*, if you just need a few specific properties from a single file this method is a quick way to get them. The results appear as they do in Explorer's Details view; according to your locale, with units, etc. The key shortcut here is the SHGetPropertyStoreFromParsingName function and other PS_ APIs, which let us skip over all the IShellItem interface work.
Requirements
-Windows Vista or higher
-VB6: oleexp 2.0 or higher (no new release related to this code)
-twinBASIC: Windows Development Library for twinBASIC
Usage
After putting the below code in a module, just call the GetPropertyDisplayString(file, property) function, it will return a string with the property as it appears in Explorer. For example, System.Image.Dimensions on a JPG file might return "640 x 480", or System.Width as "100 pixels"; or an AVI's System.Length as "01:30:20". It's more than just raw numbers (although those can be retrieved too; see the larger project).
sResult = GetPropertyDisplayString("C:\myfile.jpg", "System.Width")
UPDATE: (2015Dec05) - I think I would have heard about it if it was always the case; but on my system, office documents were counted as slow items even on the OS drive, and getting the IPropertyStore for them failed (0x80040154 Class not registered). This is resolved by adding flags to open slow items and always return a property store, even if some properties couldn't be loaded.
Code
Code:
'APIs optional with tB/WinDevLib
Public Declare Function PSGetPropertyKeyFromName Lib "propsys.dll" (ByVal pszName As LongPtr, ppropkey As PROPERTYKEY) As Long
Public Declare Function PSFormatPropertyValue Lib "propsys.dll" (ByVal pps As LongPtr, ByVal ppd As LongPtr, ByVal pdff As PROPDESC_FORMAT_FLAGS, ppszDisplay As LongPtr) As Long
Public Declare Function SHGetPropertyStoreFromParsingName Lib "shell32" (ByVal pszPath As LongPtr, pbc As Any, ByVal Flags As GETPROPERTYSTOREFLAGS, riid As UUID, ppv As Any) As Long
Public Declare Function PSGetPropertyDescription Lib "propsys.dll" (PropKey As PROPERTYKEY, riid As UUID, ppv As Any) As Long
Public Function GetPropertyDisplayString(szFile As String, szProp As String) As String
'Gets the string value of the given canonical property; e.g. System.Company, System.Rating, etc
'This would be the value displayed in Explorer if you added the column in details view
Dim pkProp As PROPERTYKEY
Dim pps As IPropertyStore
Dim lpsz As LongPtr
Dim ppd As IPropertyDescription
PSGetPropertyKeyFromName StrPtr(szProp), pkProp
SHGetPropertyStoreFromParsingName StrPtr(szFile), ByVal 0&, GPS_DEFAULT Or GPS_BESTEFFORT Or GPS_OPENSLOWITEM, IID_IPropertyStore, pps
PSGetPropertyDescription pkProp, IID_IPropertyDescription, ppd
PSFormatPropertyValue ObjPtr(pps), ObjPtr(ppd), PDFF_DEFAULT, lpsz
SysReAllocStringW VarPtr(GetPropertyDisplayString), lpsz
CoTaskMemFree lpsz
End Function
Include the following in your module only if you're not using the mIID.bas module from the oleexp thread, or WinDevLib in twinBASIC:
Code:
Public Sub DEFINE_UUID(Name As UUID, L As Long, w1 As Integer, w2 As Integer, B0 As Byte, b1 As Byte, b2 As Byte, B3 As Byte, b4 As Byte, b5 As Byte, b6 As Byte, b7 As Byte)
With Name
.Data1 = L
.Data2 = w1
.Data3 = w2
.Data4(0) = B0
.Data4(1) = b1
.Data4(2) = b2
.Data4(3) = B3
.Data4(4) = b4
.Data4(5) = b5
.Data4(6) = b6
.Data4(7) = b7
End With
End Sub
Public Function IID_IPropertyStore() As UUID
'DEFINE_GUID(IID_IPropertyStore,0x886d8eeb, 0x8cf2, 0x4446, 0x8d,0x02,0xcd,0xba,0x1d,0xbd,0xcf,0x99);
Static IID As UUID
If (IID.Data1 = 0) Then Call DEFINE_UUID(IID, &H886D8EEB, CInt(&H8CF2), CInt(&H4446), &H8D, &H2, &HCD, &HBA, &H1D, &HBD, &HCF, &H99)
IID_IPropertyStore = IID
End Function
Public Function IID_IPropertyDescription() As UUID
'(IID_IPropertyDescription, 0x6f79d558, 0x3e96, 0x4549, 0xa1,0xd1, 0x7d,0x75,0xd2,0x28,0x88,0x14
Static IID As UUID
If (IID.Data1 = 0) Then Call DEFINE_UUID(IID, &H6F79D558, CInt(&H3E96), CInt(&H4549), &HA1, &HD1, &H7D, &H75, &HD2, &H28, &H88, &H14)
IID_IPropertyDescription = IID
End Function
ALTERNATIVE: Get directly by PROPERTYKEY
Now that I've published a complete list of PROPERTYKEY's from propkey.h, if you include the mPKEY.bas module from the oleexp project, you can use those directly like this:
Code:
Public Function GetPropertyKeyDisplayString(szFile As String, pkProp As PROPERTYKEY) As String
Dim pps As IPropertyStore
Dim lpsz As LongPtr
Dim ppd As IPropertyDescription
SHGetPropertyStoreFromParsingName StrPtr(szFile), ByVal 0&, GPS_DEFAULT Or GPS_BESTEFFORT Or GPS_OPENSLOWITEM, IID_IPropertyStore, pps
PSGetPropertyDescription pkProp, IID_IPropertyDescription, ppd
PSFormatPropertyValue ObjPtr(pps), ObjPtr(ppd), PDFF_DEFAULT, lpsz
SysReAllocStringW VarPtr(GetPropertyKeyDisplayString), lpsz
CoTaskMemFree lpsz
End Function
Common Properties
For a full list of system properties, see propkey.h in the SDK (or unofficial copies online); or the larger projects I have that will enumerate them all.
Otherwise, see the MSDN post Metadata Properties for Media Files for the popular ones.
-------------------------------
* - When working with large numbers of files, or user-selectable properties, it's best to implement IShellItem and IPropertySystem based solutions from the ground up.
Last edited by fafalone; Mar 9th, 2026 at 08:43 AM.
Reason: Update for tB/x64 compatibility
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|