Jonathan Gilbert
Jonathan Gilbert

Reputation: 3840

Windows Explorer & custom shortcut file types

Windows has a flag in file registrations called "IsShortcut". When this flag is set, the file is automatically given the shortcut icon overlay and is treated as a shortcut in other ways (for instance, when you right click and select "Create Shortcut", it simply copies the file instead of generating a .lnk file). Microsoft uses this feature for ClickOnce Application References (extension .appref-ms).

We use this feature for a custom shortcut file type for our own software, and what we have found is that since Windows 10 (or possibly Windows 8), our custom shortcuts do not appear in the Start Menu. The Start Menu of course lists .lnk files, and it does include .appref-ms files as well, but our own file format, whose registration does not appear substantively different from .appref-ms files, is excluded from the Start Menu. The shortcut files are physically present within the Start Menu folder structure (%APPDATA%\Microsoft\Windows\Start Menu\Programs) but are ignored by Windows Explorer. Other shortcut types (.lnk and .appref-ms) in the same directory do show up.

What I'm looking for is some indication of how Windows Explorer determines which file formats it will include in the Start Menu, so that when developing a custom format, it can be indicated in the same manner. Our custom format worked fine in Windows XP, Windows Vista and Windows 7, but the newer Start Menu design for some reason excludes our file format, even though it is marked IsShortcut in the same manner as .appref-ms files.

Is this possible to do? :-)

Upvotes: 0

Views: 683

Answers (2)

user234878
user234878

Reputation: 68

To show the link in Windows 10 startmenu, IPropertyStore.GetValue must be implemented and return some unique string for PKEY_AppUserModel_ID property.

To show the icon in Windows 10 startmenu, IExtractIconW.GetIconLocation must be implemented and owner of the registry key with CLSID class (i.e. HKEY_CLASSES_ROOT\CLSID{42465C3A-83D3-4310-B27D-F271DE372764}) must be "NT Service\TrustedInstaller"

Here is sample implementation (enhanced Jonathan Gilbert code): https://github.com/publee/CustomShortcutFileType

Upvotes: 2

Denis Anisimov
Denis Anisimov

Reputation: 3317

(This is not the answer, but may help you in your investigations.)

I created and registred my own shell link extension. After Explorer restarts it uses my extension and asks different properties via IPropertyStore interface. Full log:

TMyLinkExtension.07BA12F0 is created
  TMyLinkExtension.07BA12F0.QueryInterface IID_IShellLinkW out Result=S_OK
  TMyLinkExtension.07BA12F0.QueryInterface IID_IInitializeWithFile out Result=S_OK
  TMyLinkExtension.07BA12F0.IInitializeWithFile.Initialize started
    TMyLinkExtension.07BA12F0.IInitializeWithFile.Initialize in AFileName=C:\Users\Dec\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Total Commander\1.mylnk
    TMyLinkExtension.07BA12F0.IInitializeWithFile.Initialize in AOpenMode=STGM_READ
    TMyLinkExtension.07BA12F0.IInitializeWithFile.Initialize out Result=S_OK
  TMyLinkExtension.07BA12F0.IInitializeWithFile.Initialize finished
  TMyLinkExtension.07BA12F0.QueryInterface IID_IShellLinkW out Result=S_OK
  TMyLinkExtension.07BA12F0.QueryInterface IID_IShellLinkDataList out Result=S_OK
  TMyLinkExtension.07BA12F0.IShellLinkDataList.GetFlags started
    TMyLinkExtension.07BA12F0.IShellLinkDataList.GetFlags out Result=E_NOTIMPL
  TMyLinkExtension.07BA12F0.IShellLinkDataList.GetFlags finished
  TMyLinkExtension.07BA12F0.IShellLinkW.GetPath started
    TMyLinkExtension.07BA12F0.IShellLinkW.GetPath in AFileName=0C1FF058
    TMyLinkExtension.07BA12F0.IShellLinkW.GetPath in AFileNameLength=260
    TMyLinkExtension.07BA12F0.IShellLinkW.GetPath in @AFindData=0C1FEE08
    TMyLinkExtension.07BA12F0.IShellLinkW.GetPath in AFlags=SLGP_RAWPATH
    TMyLinkExtension.07BA12F0.IShellLinkW.GetPath out Result=E_NOTIMPL
  TMyLinkExtension.07BA12F0.IShellLinkW.GetPath finished
  TMyLinkExtension.07BA12F0.QueryInterface IID_IPropertyStore out Result=S_OK
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue started
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue in AKey=PKEY_AppUserModel_ID (Caption: AppUserModelId, CanonicalName: System.AppUserModel.ID, Type: VT_LPWSTR)
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue out Result=E_INVALIDARG
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue finished
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue started
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue in AKey=PKEY_AppUserModel_PreventPinning (Caption: Prevent pinning, CanonicalName: System.AppUserModel.PreventPinning, Type: VT_BOOL)
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue out AData.vt=VT_BOOL
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue out AData=0
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue out Result=S_OK
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue finished
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue started
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue in AKey={9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 23 (Caption: System.AppUserModel.ExcludedFromLauncher, CanonicalName: System.AppUserModel.ExcludedFromLauncher, Type: VT_BOOL)
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue out AData.vt=VT_BOOL
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue out AData=0
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue out Result=S_OK
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue finished
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue started
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue in AKey={9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 14 (Caption: Host environment, CanonicalName: System.AppUserModel.HostEnvironment, Type: VT_UI4)
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue out Result=E_INVALIDARG
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue finished
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue started
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue in AKey=PKEY_AppUserModel_StartPinOption (Caption: Start pin option, CanonicalName: System.AppUserModel.StartPinOption, Type: VT_UI4)
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue out Result=E_INVALIDARG
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue finished
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue started
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue in AKey={9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 18 (Caption: Installed by, CanonicalName: System.AppUserModel.InstalledBy, Type: VT_UI4)
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue out Result=E_INVALIDARG
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue finished
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue started
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue in AKey=PKEY_AppUserModel_IsDualMode (Caption: Is dual mode, CanonicalName: System.AppUserModel.IsDualMode, Type: VT_BOOL)
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue out Result=E_INVALIDARG
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue finished
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue started
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue in AKey=PKEY_Link_Arguments (Caption: Arguments, CanonicalName: System.Link.Arguments, Type: VT_LPWSTR)
    TMyLinkExtension.07BA12F0.IPropertyStore.GetValue out Result=E_INVALIDARG
  TMyLinkExtension.07BA12F0.IPropertyStore.GetValue finished
TMyLinkExtension.07BA12F0 is destroyed

I tried to play with different values but still cant find the way to show my 1.mylnk file in the start menu but maybe this log will help you.

Upvotes: 1

Related Questions