Displaying all Windows Shell properties for all items in a given folder
See the question and my original answer on StackOverflowHere is some sample code (using ATL for smart pointers) that displays all properties for all items in the recycle bin (or any other folder you'd like).
You can pick the properties you want. I've dumped a sample output with a deleted txt file. The item's display name actually depends on the maching settings, but you can see there are lots of other interesting properties, for example:
System.Recycle.DeletedFrom
(eq to SCID_RemovedFrom)System.Recycle.DateDeleted
(eq to SCID_DateDeleted)System.ItemNameDisplay
(note for virtual items, you won't always have a System.FileName)System.ItemType
(note for virtual items, you won't always have a System.FileExtension)
Sample output:
D:\temp\New Text Document.txt // this is the normal display name (depends on settings)
System.ItemFolderNameDisplay = Recycle Bin
System.ItemTypeText = Text Document
System.ItemNameDisplay = New Text Document.txt
System.Size = 0
System.FileAttributes = 33
System.DateModified = 2019/12/04:17:52:05.132
System.DateCreated = 2019/12/04:17:52:06.000
System.DateAccessed = 2019/12/04:17:52:06.000
System.ItemNameDisplayWithoutExtension = $RWLK87M
System.ContentType = text/plain
System.Document.DateCreated = 2019/12/04:17:52:05.132
System.Document.DateSaved = 2019/12/04:17:52:05.132
System.Recycle.DeletedFrom = D:\temp
System.Recycle.DateDeleted = 2021/02/16:08:18:46.000
System.FileOwner = KILLROY\WasHere
System.NetworkLocation =
System.ComputerName = KILLROY
System.ItemPathDisplayNarrow = $RWLK87M (D:\$RECYCLE.BIN\Recycle Bin)
System.PerceivedType = 1
System.ItemType = .txt
System.ParsingName = D:\$RECYCLE.BIN\S-1-5-21-2804694453-2728412037-1988799983-1001\$RWLK87M.txt
System.SFGAOFlags = 1077936503
System.ParsingPath = D:\$RECYCLE.BIN\S-1-5-21-2804694453-2728412037-1988799983-1001\$RWLK87M.txt
System.FileExtension = .txt
System.ItemDate = 2019/12/04:17:52:05.132
System.KindText = Document
System.FileAttributesDisplay = Read-only
System.IsShared = 0
System.SharedWith =
System.SharingStatus = 2
System.ShareScope =
System.Security.EncryptionOwnersDisplay =
System.ItemName = $RWLK87M.txt
System.Shell.SFGAOFlagsStrings = filesys; stream
System.Link.TargetSFGAOFlagsStrings =
System.OfflineAvailability =
System.ZoneIdentifier = 0
System.LastWriterPackageFamilyName =
System.AppZoneIdentifier =
System.Kind = document
System.Security.EncryptionOwners =
System.ItemFolderPathDisplayNarrow = Recycle Bin (D:\$RECYCLE.BIN)
System.FileName = New Text Document.txt
System.Security.AllowedEnterpriseDataProtectionIdentities =
System.ThumbnailCacheId = 11524143073100486861
System.VolumeId = {184CD9C9-570E-483F-9AE1-68D57270A239}
System.Link.TargetParsingPath =
System.Link.TargetSFGAOFlags =
System.ItemFolderPathDisplay = D:\$RECYCLE.BIN\Recycle Bin
System.ItemPathDisplay = D:\$RECYCLE.BIN\Recycle Bin\$RWLK87M.txt
{9E5E05AC-1936-4A75-94F7-4704B8B01923} 0 = New Text Document.txt
System.AppUserModel.ID =
System.AppUserModel.ParentID =
System.Link.TargetExtension =
System.OfflineStatus =
System.IsFolder = 0
System.NotUserContent = 0
System.StorageProviderAggregatedCustomStates =
System.SyncTransferStatusFlags =
System.DateImported = 2019/12/04:17:52:05.132
System.ExpandoProperties =
System.FilePlaceholderStatus = 6
Sample code:
#include <iostream>
#include <shobjidl_core.h>
#include <shlobj.h>
#include <propvarutil.h>
#include <atlbase.h>
#include <atlcom.h>
#pragma comment(lib, "propsys")
int main() {
HRESULT hr = CoInitialize(nullptr);
{
// get recycle bin folder
CComPtr<IShellItem> bin;
hr = SHCreateItemInKnownFolder(FOLDERID_RecycleBinFolder, 0, nullptr, IID_PPV_ARGS(&bin));
if (SUCCEEDED(hr))
{
// enumerate items
CComPtr<IEnumShellItems> items;
hr = bin->BindToHandler(nullptr, BHID_EnumItems, IID_PPV_ARGS(&items));
if (SUCCEEDED(hr))
{
do
{
// get item
CComPtr<IShellItem> item;
hr = items->Next(1, &item, nullptr);
if (hr != 0)
break;
// get the display name (depends on settings)
CComHeapPtr<wchar_t> path;
item->GetDisplayName(SIGDN_NORMALDISPLAY, &path);
std::wcout << path.m_pData << std::endl;
// get item's property store
CComPtr<IPropertyStore> store;
hr = CComQIPtr<IShellItem2>(item)->GetPropertyStore(GPS_DEFAULT, IID_PPV_ARGS(&store));
if (SUCCEEDED(hr))
{
DWORD count = 0;
store->GetCount(&count);
for (DWORD i = 0; i < count; i++)
{
// print this property (name, value)
PROPERTYKEY pk;
hr = store->GetAt(i, &pk);
if (SUCCEEDED(hr))
{
// get property canonical name
CComHeapPtr<wchar_t> name;
PSGetNameFromPropertyKey(pk, &name);
// get property value
PROPVARIANT pv;
PropVariantInit(&pv);
hr = store->GetValue(pk, &pv);
if (SUCCEEDED(hr))
{
CComHeapPtr<wchar_t> value;
hr = PropVariantToStringAlloc(pv, &value); // propvarutil.h
if (SUCCEEDED(hr))
{
if (!name) // unknown name
{
CComHeapPtr<wchar_t> fmtid;
StringFromCLSID(pk.fmtid, &fmtid);
std::wcout << L" " << fmtid.m_pData << L" " << pk.pid << L" = " << value.m_pData << std::endl;
}
else
{
std::wcout << L" " << name.m_pData << L" = " << value.m_pData << std::endl;
}
}
else
{
// can't convert to string, print something useful
}
}
PropVariantClear(&pv);
}
}
}
} while (true);
}
}
}
CoUninitialize();
return 0;
}