windows - How to use SHCreateItemFromParsingName with names from the shell namespace? -
i using shcreateitemfromparsingname turn path ishellitem:
ishellitem parsename(string path) { ishellitem shellitem; hresult hr = shcreateitemfromparsingname(path, null, ishellitem, out shellitem); if (failed(hr)) throw new ecomexception(hr); return shellitem; } note:
ishellitemintroduced around 2006 provide handy wrapper around windows 95-eraishellfolder+pidlconstructs. can askishellitemcough it's underlyingishellfolder,pidliparentanditem.getparentanditeminterface , method.
different things have different display names
i can ahold of well-known locations in shell namespace, , see absolute parsing (sigdn_desktopabsoluteparsing) , editing (sigdn_desktopabsoluteediting) display names:
| path | editing | parsing | |-------------------|-----------------------|-------------------------------------------------------------------| | c:\ | "c:\" | "c:\" | | c:\windows | "c:\windows" | "c:\windows" | | desktop | "desktop" | "c:\users\ian\desktop" | | computer | "this pc" | "::{20d04fe0-3aea-1069-a2d8-08002b30309d}" | | recycle bin | "recycle bin" | "::{645ff040-5081-101b-9f08-00aa002f954e}" | | documents library | "libraries\documents" | "::{031e4825-7b94-4dc3-b131-e946b44c8dd5}\documents.library-ms" " | | startup | "c:\users\ian\appdata\roaming\microsoft\windows\start menu\programs\startup" | "c:\users\ian\appdata\roaming\microsoft\windows\start menu\programs\startup" | how parse them when user types in them in?
i can use ifileopendialog let user select 1 of these folders. i'd user able type
- "c:\users"
- "c:\windows\fonts"
- "this pc"
- "recycle bin"
- "libraries"
- "startup"
- "fonts"
and able parse ishellitem.
the problem of paths not parsed shcreateitemfromparsingname:
shcreateitemfromparsingname("c:\"): parsesshcreateitemfromparsingname("c:\windows"): parsesshcreateitemfromparsingname(""): parses (but becomes "this pc")shcreateitemfromparsingname("this pc"): failsshcreateitemfromparsingname("recycle bin"): failsshcreateitemfromparsingname("libraries"): failsshcreateitemfromparsingname("onedrive"): failsshcreateitemfromparsingname("libraries\documents"): failsshcreateitemfromparsingname("network"): failsshcreateitemfromparsingname("startup"): fails
meanwhile, ifileopendialog control program uses can parse them fine:
how can parse various special shell name places user might type in (that windows explorer , ifileopen dialog can parse) ishellitem folder?
the real question want user able have recent mru list contains things like:
- c:\windows
- recycle bin
- this pc
and able parse them later.
it interesting debug explorer , see how it.
my suggestion is; if initial parse fails, prepend shell: path string , try parsing again shparsedisplayname. if set str_parse_shell_protocol_to_file_objects in bind context can bind special files. shell: protocol able parse internal/canonical name of special/known folders don't know if checks display name.
edit:
i had chance play around bit , shell: prefix not huge improvement because checks known folder canonical names:
pcwstr paths[] = { text("c:\\"), text("c:\\windows"), text(""), text("this pc"), text("mycomputerfolder"), // canonical kf name text("recycle bin"), text("recyclebinfolder"), // canonical kf name text("libraries"), text("onedrive"), text("libraries\\documents"), text("network"), text("networkplacesfolder"), // canonical kf name text("startup"), }; oleinitialize(0); int pad = 0, fill, i; (i = 0; < arraysize(paths); ++i) pad = max(pad, lstrlen(paths[i])); (i = 1, fill = printf("%-*s | original | shell: |\n", pad, ""); < fill; ++i) printf("-"); printf("\n"); (i = 0; < arraysize(paths); ++i) { wchar buf[max_path], *p1 = null, *p2 = null; ishellitem*psi; hresult hr = shcreateitemfromparsingname(paths[i], null, iid_ishellitem, (void**) &psi); if (succeeded(hr)) psi->getdisplayname(sigdn_desktopabsoluteparsing, &p1), psi->release(); wsprintf(buf, l"shell:%s", paths[i]); hresult hr2 = shcreateitemfromparsingname(buf, null, iid_ishellitem, (void**) &psi); if (succeeded(hr2)) psi->getdisplayname(sigdn_desktopabsoluteparsing, &p2), psi->release(); wprintf(l"%-*s | %.8x | %.8x | %s\n", pad, paths[i], hr, hr2, p2 && *p2 ? p2 : p1 ? p1 : l""); cotaskmemfree(p1), cotaskmemfree(p2); } gives me output:
| original | shell: | ------------------------------------------- c:\ | 00000000 | 80070003 | c:\ c:\windows | 00000000 | 80070003 | c:\windows | 00000000 | 80070003 | ::{20d04fe0-3aea-1069-a2d8-08002b30309d} pc | 80070002 | 80070003 | mycomputerfolder | 80070002 | 00000000 | ::{20d04fe0-3aea-1069-a2d8-08002b30309d} recycle bin | 80070002 | 80070003 | recyclebinfolder | 80070002 | 00000000 | ::{645ff040-5081-101b-9f08-00aa002f954e} libraries | 80070002 | 00000000 | ::{031e4825-7b94-4dc3-b131-e946b44c8dd5} onedrive | 80070002 | 80070003 | libraries\documents | 80070002 | 80070002 | network | 80070002 | 80070003 | networkplacesfolder | 80070002 | 00000000 | ::{f02c1a0d-be21-4350-88b0-7367fc96ef3c} startup | 80070002 | 00000000 | c:\users\anders\appdata\roaming\microsoft\windows\start menu\programs\startup on windows 8 shcreateitemfromparsingname calls shparsedisplayname (with str_parse_and_create_item , str_parse_translate_aliases) microsoft have trouble separating parsing , display names in api.
if want stay away undocumented interfaces have add third pass check known folder display names. or alternatively raymond chen suggests in comments; parse every path component manually against item display names in ishellfolder.

Comments
Post a Comment