Properties coding expedition #1 - Binding to an item
The goal of this first expedition is to print lists of properties from items. This will give insight into the origins and capabilities of these different properties. Feel free to follow along and try out different things. There's a lot to explore.
I am splitting this and future programming expeditions into segments so that I can talk about the details without posting miles of code.
#include <windows.h> #include <propsys.h> #include <propvarutil.h> #include <propkey.h> #include <shobjidl.h> #include <stdio.h> #pragma comment(lib, "propsys.lib") #pragma comment(lib, "ole32.lib") #pragma comment(lib, "shlwapi.lib") #pragma comment(lib, "shell32.lib") int wmain(__in int argc, __in_ecount(argc) WCHAR **argv) { HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); if (SUCCEEDED(hr)) { if (argc == 0) { wprintf(L"Usage: %s \n", argv[0]); } else { PCWSTR pszFile = argv[1]; wprintf(L"Properties for '%s'\n", pszFile); WCHAR szDir[MAX_PATH]; if (GetCurrentDirectory(ARRAYSIZE(szDir), szDir)) { WCHAR szPath[MAX_PATH]; if (PathCombineW(szPath, szDir, pszFile)) { IShellItem2 *psi; hr = SHCreateItemFromParsingName(szPath, NULL, IID_PPV_ARGS(&psi)); if (SUCCEEDED(hr)) { IPropertyStore *pps; hr = psi->GetPropertyStore(GPS_DEFAULT, IID_PPV_ARGS(&pps)); if (SUCCEEDED(hr)) { hr = _PrintPropertyStore(pps); pps->Release(); } psi->Release(); } } } } CoUninitialize(); } }
There's nothing too special about this code. Starting with some boilerplate, we figure out the path to the file, bind to it, and grab it's property store. Tomorrow I'll dive into the printing loop.
SHCreateItemFromParsingName is a nifty little function. IShellItem has been around for some time, but it was never this easy to obtain.
On Windows 2000, you had to:
- Call SHGetDesktopFolder to get the desktop's IShellFolder interface
- Call IShellFolder::ParseDisplayName to get the PIDLIST_RELATIVE for the item
- Call SHCreateShellItem to get the IShellItem interface
Windows XP made this easier with SHParseDisplayName which took care of steps 1 and 2.
Windows Vista provides SHCreateItemFromParsingName to take care of steps 1, 2 and 3 all at once!
-Ben Karas
Comments
- Anonymous
October 03, 2006
here is a useful helper I created for some of my test apps.produce a shell item from the command line. deals with unquoting paths.STDAPI GetShellItemFromCommandLine(REFIID riid, void **ppv){ *ppv = NULL; HRESULT hr = E_FAIL; int cArgs; PWSTR *ppszCmd = CommandLineToArgvW(GetCommandLineW(), &cArgs); if (ppszCmd && cArgs > 1) { WCHAR szSpec[MAX_PATH]; StringCchCopyW(szSpec, ARRAYSIZE(szSpec), ppszCmd[1]); PathUnquoteSpacesW(szSpec); hr = szSpec[0] ? S_OK : E_FAIL; // protect against empty if (SUCCEEDED(hr)) { hr = SHCreateItemFromParsingName(szSpec, NULL, riid, ppv); if (FAILED(hr)) { WCHAR szFolder[MAX_PATH]; GetCurrentDirectoryW(ARRAYSIZE(szFolder), szFolder); hr = PathAppendW(szFolder, szSpec) ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { hr = SHCreateItemFromParsingName(szFolder, NULL, riid, ppv); } } } } return hr;}and here is sample usage IShellItem *psi; hr = GetShellItemFromCommandLine(IID_PPV_ARGS(&psi)); if (SUCCEEDED(hr)) { PWSTR pszName; hr = psi->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &pszName); if (SUCCEEDED(hr)) { CoTaskMemFree(pszName); } psi->Release(); } - Anonymous
October 04, 2006
Wow, I forgot about that attachment! Ha! It's the picture I'm going to use when testing this program. It also shows what properties Window Vista chooses to show for this filetype.http://blogs.msdn.com/benkaras/attachment/777894.ashx - Anonymous
November 05, 2006
This coding expedition has developed a tool that can dump out all the properties on a file. If you are