Image may be NSFW.
Clik here to view.
It's easy to show the file property window for a single file with ShellExecuteEx, but what if you wanted to also show a property window for multiple files in multiple paths as you can do in Explorer? The ShellExecuteEx method provides no option to pass an array of files. So you have to turn to SHMultiFileProperties. The reason this has never been done in VB before (at least as far as I could find with Google), is that it requires an IDataObject to describe the files, and that's traditionally been a tough thing to do. But thanks to some shell32 API's, it's not as bad as you'd think.Clik here to view.

There's two APIs we can use to get the needed IDataObject, SHCreateDataObject and SHCreateFileDataObject. The former is only available on Vista and higher, and the latter is undocumented and exported by ordinal only. However, it's been at the same ordinal from XP through 8.1 (haven't checked 10), so I'll use that in the sample code. If you don't need to support XP, switch it out- they're extremely similar.
Requirements
Windows XP or higher
For the IDE only, a type library containing the definition for IDataObject. Some versions of OLEGuids might work, but I recommend using my Modern Interfaces Type Library, although just the original version of olelib would be sufficient. Simply download and add a reference to olelib.tlb to your project.
Code
Code:
Public Declare Function SHCreateFileDataObject Lib "shell32" Alias "#740" (ByVal pidlFolder As Long, ByVal cidl As Long, ByVal apidl As Long, pDataInner As Any, ppDataObj As olelib.IDataObject) As Long
'For Vista+ if you wanted:
'Public Declare Function SHCreateDataObject Lib "shell32" (ByVal pidlFolder As Long, ByVal cidl As Long, ByVal apidl As Long, pdtInner As Any, riid As UUID, ppv As Any) As Long
Public Declare Function SHMultiFileProperties Lib "shell32" (ByVal pdtobj As Long, ByVal dwFlags As Long) As Long
Public Declare Function ILCreateFromPathW Lib "shell32" (ByVal pwszPath As Long) As Long
Public Declare Sub ILFree Lib "shell32" (ByVal pidl As Long)
Public Sub ShowMultiFileProperties(sFiles() As String)
'Displays merged file properties window
'Will also display normal property window if a single file is passed
'Unicode is supported
Dim pData As olelib.IDataObject 'always explicitly type this with the parent
Dim apidl() As Long
Dim cpidl As Long
Dim i As Long
ReDim apidl(UBound(sFiles))
If (UBound(sFiles) = 0) And (sFiles(0) = "") Then Exit Sub
For i = 0 To UBound(sFiles)
apidl(i) = ILCreateFromPathW(StrPtr(sFiles(i))) 'create a fully qualified pidl for each file
Next i
cpidl = UBound(apidl) + 1
Call SHCreateFileDataObject(VarPtr(0), cpidl, VarPtr(apidl(0)), ByVal 0&, pData) 'VarPtr(0) is always equal to the desktop's pidl
If (pData Is Nothing) Then
Debug.Print "ShowMultiFileProperties: Could not create data object"
Exit Sub
End If
Call SHMultiFileProperties(ObjPtr(pData), 0) 'passing IDataObject ByRef like you'd think from MSDN results in a crash, so the declare is changed to Long and we send the object pointer
Set pData = Nothing
For i = 0 To UBound(apidl)
ILFree apidl(i) 'never forget to set your pidls free
Next i
End Sub