Results 1 to 9 of 9

Thread: [RESOLVED] StartMenu Shortcuts not Appearing from API

  1. #1

    Thread Starter
    Member lmstearn's Avatar
    Join Date
    Dec 2016
    Location
    Australia
    Posts
    58

    Resolved [RESOLVED] StartMenu Shortcuts not Appearing from API

    Hi there,
    Have this code run through Win 10 (1809):

    Code:
    StartMenuPath = GetSpecialFolder(CSIDL_STARTMENU)
    StartMenuPath = StartMenuPath & "Programs\MyApp\"
    fCreateShellLink StartMenuPath & Mid(currentdirectory, ct1 + 1, dirlen - ct1) & ".lnk", App.Path & "\MyApp.exe", currentdirectory, App.Path & "\MyApp.exe", indexoficon, startupmode
    The lnk files are created beautifully by the API in the target MyApp subdirectory of StartMenuPath. They don't appear in the LH StartMenu popup, however. Manually created lnks do. Compared the properties of the manual lnks and the script created ones. No difference except the script created ones have text in the comment section.
    Something about the way this function is called makes TileDataLayer ignore programmatic changes to the Start Menu folder.
    Suspect TileDataLayer relies on Windows Indexing, unless edits are made to the folder via the shell.
    If that's the case, then it's a wait for the index to update, unless someone has a super "Index_This_Folder_Now" script handy.
    This PS script also looks interesting, especially for those who like killing explorer- but it won't hurry the indexing!

    Edit: But that can't be it, as made a copy of one of the program created links in the Start Menu folder, via the explorer interface. No TileDataLayer update! Copy/pasting any other link in that folder, it works. So there must be something wrong with the lnk file itself then.
    It also might be the shell now ignores CSIDL_STARTMENU and looks for the FOLDERID_StartMenu GUID -although there's no indication from MS the CSIDL will fail. If that's the case, then it must be done with another API- any suggestions?
    Thanks for reading!
    Last edited by lmstearn; Dec 29th, 2018 at 09:43 PM. Reason: More info

  2. #2
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,653

    Re: StartMenu Shortcuts not Appearing from API

    If the problem is Windows not knowing the file has been created, have you tried explicitly notifying it?

    Code:
    Public Declare Function SHChangeNotify Lib "shell32.dll" (ByVal wEventId As SHCN_Events, ByVal uFlags As SHCN_Flags, ByVal dwItem1 As Long, ByVal dwItem2 As Long) As Long
    
    Public Enum SHCN_Flags
      SHCNF_IDLIST = &H0                ' LPITEMIDLIST
      SHCNF_PATHA = &H1               ' path name
      SHCNF_PRINTERA = &H2         ' printer friendly name
      SHCNF_DWORD = &H3             ' DWORD
      SHCNF_PATHW = &H5              ' path name
      SHCNF_PRINTERW = &H6        ' printer friendly name
      SHCNF_TYPE = &HFF
      ' Flushes the system event buffer. The function does not return until the system is
      ' finished processing the given event.
      SHCNF_FLUSH = &H1000
      ' Flushes the system event buffer. The function returns immediately regardless of
      ' whether the system is finished processing the given event.
      SHCNF_FLUSHNOWAIT = &H2000
    
      SHCNF_PATH = SHCNF_PATHW
      SHCNF_PRINTER = SHCNF_PRINTERW
    
    End Enum
    
    Public Const SHCNE_CREATE = &H2 'I've omitted the full enum, you can look up all the other events if you need them
    Then SHChangeNotify SHCNE_CREATE, SHCNF_PATH, StrPtr("C:\path\tofile.txt.lnk")
    Sometimes it takes Explorer a while to notice a file that was created with some lower level APIs, and the above is what I use to have folders update immediately instead of waiting for Explorer to notice on its own.

    ---
    The CSIDL and FOLDERID are for retrieving the location; Windows won't even know which one you used when you write to that location. And to confirm it's not the link itself, does it work when you double click it in Explorer?

  3. #3

    Thread Starter
    Member lmstearn's Avatar
    Join Date
    Dec 2016
    Location
    Australia
    Posts
    58

    Re: StartMenu Shortcuts not Appearing from API

    Quote Originally Posted by fafalone View Post
    If the problem is Windows not knowing the file has been created, have you tried explicitly notifying it?

    Code:
    Public Declare Function SHChangeNotify Lib "shell32.dll" (ByVal wEventId As SHCN_Events, ByVal uFlags As SHCN_Flags, ByVal dwItem1 As Long, ByVal dwItem2 As Long) As Long
    
    Public Enum SHCN_Flags
      SHCNF_IDLIST = &H0                ' LPITEMIDLIST
      SHCNF_PATHA = &H1               ' path name
      SHCNF_PRINTERA = &H2         ' printer friendly name
      SHCNF_DWORD = &H3             ' DWORD
      SHCNF_PATHW = &H5              ' path name
      SHCNF_PRINTERW = &H6        ' printer friendly name
      SHCNF_TYPE = &HFF
      ' Flushes the system event buffer. The function does not return until the system is
      ' finished processing the given event.
      SHCNF_FLUSH = &H1000
      ' Flushes the system event buffer. The function returns immediately regardless of
      ' whether the system is finished processing the given event.
      SHCNF_FLUSHNOWAIT = &H2000
    
      SHCNF_PATH = SHCNF_PATHW
      SHCNF_PRINTER = SHCNF_PRINTERW
    
    End Enum
    
    Public Const SHCNE_CREATE = &H2 'I've omitted the full enum, you can look up all the other events if you need them
    Then SHChangeNotify SHCNE_CREATE, SHCNF_PATH, StrPtr("C:\path\tofile.txt.lnk")
    Sometimes it takes Explorer a while to notice a file that was created with some lower level APIs, and the above is what I use to have folders update immediately instead of waiting for Explorer to notice on its own.

    ---
    The CSIDL and FOLDERID are for retrieving the location; Windows won't even know which one you used when you write to that location. And to confirm it's not the link itself, does it work when you double click it in Explorer?
    Hey Falafone- also noted your contributions on these functions, especially this, thanks.
    This is what I tried:
    Code:
    SHChangeNotify SHCNE_CREATE, SHCNF_PATH, StrPtr(fullStartMenuName), 0
    SHChangeNotify SHCNE_UPDATEDIR, SHCNF_PATH, StrPtr(fullStartMenuName), 0
    The second call may not be necessary.
    Worked even better on the XP machine when the item popped up on the Recent list. Sadly, not in this machine, which for yet to be discovered reasons is host to a rather unstable edition of explorer.
    Will attempt it again on a fresh boot- or else rebuild the Start menu database before reporting back.
    Last edited by lmstearn; Dec 29th, 2018 at 09:21 PM.

  4. #4

    Thread Starter
    Member lmstearn's Avatar
    Join Date
    Dec 2016
    Location
    Australia
    Posts
    58

    Re: StartMenu Shortcuts not Appearing from API

    Sorry, never posted the actual function- it looks like you've seen it before in any case:
    Code:
    Private Function fCreateShellLink(sLnkFile As String, sExeFile As String, sWorkDir As String, sIconFile As String, lIconIdx As Long, ShowCmd As SHOWCMDFLAGS) As Long
    
    Dim cShellLink   As ShellLinkA   ' An explorer IShellLinkA(Win 9x/Win NT) instance
    Dim cPersistFile As IPersistFile ' An explorer IPersistFile instance
        
    If (sLnkFile = "") Or (sExeFile = "") Then Exit Function
    
    On Error GoTo fCreateShellLinkError
    Set cShellLink = New ShellLinkA   'Create new IShellLink interface
    Set cPersistFile = cShellLink     'Implement cShellLink's IPersistFile interface
        
    With cShellLink
        'Set command line exe name & path to new ShortCut.
        .SetPath sExeFile
        
        'Set working directory in shortcut
        If sWorkDir <> "" Then .SetWorkingDirectory sWorkDir
       
        
        'Set shortcut description
        .SetDescription "MyApp" & vbNullChar
    '   If (LnkDesc <> "") Then .SetDescription pszName
        
        'Set shortcut icon location & index
        If sIconFile <> "" Then .SetIconLocation sIconFile, lIconIdx
        
        'Set shortcut's startup mode (min,max,normal)
        .SetShowCmd ShowCmd
    End With
    
    cShellLink.Resolve 0, SLR_UPDATE
    cPersistFile.Save StrConv(sLnkFile, vbUnicode), 0 'Unicode conversion that must be done!
    fCreateShellLink = True                           'Return Success
    
    fCreateShellLinkError:
    Set cPersistFile = Nothing
    Set cShellLink = Nothing
    End Function
    The code you posted here from the (now 404) vbAccelerator link (edit: now at Github) may have the missing pieces:
    Code:
    Public Sub SaveNewLink(sLink As String, _
                           sPath As String, _
                           Optional sIconFile As String = vbNullString, _
                           Optional ByVal lIcon As Long = 0, _
                           Optional ByVal iHK As Integer = 0, _
                           Optional sArgs As String = vbNullString, _
                           Optional sDesc As String = vbNullString, _
                           Optional ByVal pidl As Long = 0, _
                           Optional sWorkDir As String = vbNullString, _
                           Optional sRelPath As String = vbNullString, _
                           Optional swc As EShowWindowFlags = SW_NORMAL)
    Dim csl As CShellLink
    Dim ipf As IPersistFileVB
    
    Set csl = New CShellLink
    Set ipf = csl
    With csl
        .SetPath (sPath)
        .SetArguments sArgs
        .SetDescription sDesc
        .SetIconLocation sIconFile, lIcon
        .Hotkey = iHK
        .ShowCmd = swc
        .SetRelativePath sRelPath, 0
        .SetWorkingDirectory sWorkDir
        If pidl Then .SetIDList pidl
        
        .Resolve 0, SLR_UPDATE
        
    End With
    
    ipf.Save sLink, 0
    
    Set ipf = Nothing
    Set csl = Nothing
    The first code block uses ShellLinkA, does the second use ShellLinkW? That may require UTF8 conversion however. Perhaps Tile Store expects something else in the Unicode string - extended information or something?
    Edit: There's good info on ShellLink again at Github: maybe the answer is there.
    Last edited by lmstearn; Dec 30th, 2018 at 09:24 PM. Reason: More Info

  5. #5
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,653

    Re: StartMenu Shortcuts not Appearing from API

    I've since updated that function to use Unicode via the IShellLinkW/ShellLinkW interface in my typelib,

    Code:
    Private Sub SaveNewLink(sLink As String, _
                           sPath As String, _
                           Optional sIconFile As String = vbNullString, _
                           Optional ByVal lIcon As Long = 0, _
                           Optional ByVal iHK As Integer = 0, _
                           Optional sArgs As String = vbNullString, _
                           Optional sDesc As String = vbNullString, _
                           Optional ByVal pidl As Long = 0, _
                           Optional sWorkDir As String = vbNullString, _
                           Optional sRelPath As String = vbNullString, _
                           Optional swc As ShowWindow = SW_NORMAL)
    
    On Error GoTo e0
    
    Dim csl As ShellLinkW
    Dim ipf As IPersistFile
    
    Set csl = New ShellLinkW
    Set ipf = csl
    With csl
        .SetPath (sPath)
        .SetArguments sArgs
        .SetDescription sDesc
        .SetIconLocation sIconFile, lIcon
        .SetHotkey iHK
        .SetShowCmd swc
        .SetRelativePath sRelPath, 0
        .SetWorkingDirectory sWorkDir
        If pidl Then .SetIDList pidl
        
        .Resolve 0, SLR_UPDATE
        
    End With
    
    ipf.Save sLink, 0
    
    Set ipf = Nothing
    Set csl = Nothing
    
    Exit Sub
    
    e0:
    Debug.Print "SaveNewLink.Error->" & Err.Description & " (" & Err.Number & ")"
    
    End Sub
    As to the original problem; it's possible to force a reindex, but a little complicated, especially because it doesn't seem like there's an existing typelib that contains the search API interfaces; there's one in the SDK but it doesn't look VB friendly.
    Before going down that road, does going to the folder and hitting refresh work? If that works, you can do that programmatically...
    With my TLB and IID module or other method of accessing these interfaces...
    Code:
    Dim isi As IShellItem
    Dim psv As IShellView
    
    SHCreateItemFromParsingName StrPtr(FullPath), Nothing, IID_IShellItem, isi
    isi.BindToHandler 0&, BHID_SFViewObject, IID_IShellView, psv
    psv.Refresh
    If even that doesn't work I'm not sure that forcing a re-index will either, but if you wanted to pursue it you'd want to look at ISearchCatalogManager::ReindexMatchingURLs and example.


    PS- I should have clarified, the links in question are in fact working if you double click them right?
    Last edited by fafalone; Dec 30th, 2018 at 10:01 PM.

  6. #6
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: StartMenu Shortcuts not Appearing from API

    I seriously doubt that Windows Search plays any role here.

  7. #7
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: StartMenu Shortcuts not Appearing from API

    Maybe see Windows 10 Start Layout Customization?

    Frequently Asked Questions

    Q) Is it possible to programmatically modify the start screen through an API.

    A) No. There is no API that allows programmatic access to the Start Layout. The Start Layout XML could be programmatically edited to automatically customize the Start Layout.

  8. #8

    Thread Starter
    Member lmstearn's Avatar
    Join Date
    Dec 2016
    Location
    Australia
    Posts
    58

    Re: StartMenu Shortcuts not Appearing from API

    @Falafone: Thanks for the code! Will try that. The re-index thing is interesting, would be involved as you say- and at best, an annoyance for the clients. There is no issue with other (generally) installer programs having their shortcuts place on this menu during the installation phase. Even @Dilettante's favourite: No-no Setup! Many of them use Wscript which may hold a secret or two.
    The link in your 2014 post was updated in 2016- so all I had to do was go to the index - there's a truckload of goodies in there.

    @Dilettante: Yes, unlikely to be the indexing service itself, Tile Store may be filtering the names/dates of the links- but could it be looking for some other data field in the lnk file? Or perhaps MS have their own secret index of popular installer programs (The_Store_List) which are endowed with magical Tile Store privileges. The answer is bound to be somewhere in your second posted link.

    Posted an issue at MS cross-linking here- because there's a veritable rats' nest of possibilities on offer:
    There's a possibility the Tile Store wants to grab the shortcut milliseconds after creation- before it's released from the creating thread. Unlikely, but ProcMon would be required to follow that through. Manually deleting the shortcut "just after" creation is successful.
    Using a hex editor, analysing a shortcut (M) created manually with the thread created one (T) shows minor differences:- the link source, or lpExeFilePath
    in (M) actually links to a file in the newly created path which is in turn linked by previous association back to the link source, lpExeFilePath. (T) links straight to the root app exe.
    The application in question, very much of legacy tech, is actually configured as a game process, although its associations with Xbox have been removed along with the removal of Xbox, it is configured to work with GameBar, which has been crashing of late.
    To verify there are no site specific issues, tried this MS Powershell example- no shortcut created. But it may not have been trialed correctly. Other programs & installers have no issue creating shortcuts that duly appear on the Start menu of this computer.
    As described, the newly created shortcut uses the same base link (lpExeFilePath) as an existing one in the same shortcut folder. If Tile Store uses lpExeFilePath as a key, then to reject a duplicate key is buggo or feeping creature?
    In any event, the next trial will be not to link directly to lpExeFilePath but to another application non-executable file Associated with lpExeFilePath, noting the intention in the OP was to create a shortcut to the original application exe file but with a different working directory.
    Bit o' bizarro behaviour with manual shortcut creation when Tile Store does accept another shortcut (A) of the original file- then, when a copy (B) is created of the original lnk file in the Start Menu folder, (B) shows but (A) does not.
    Last edited by lmstearn; Dec 31st, 2018 at 04:27 PM. Reason: More Info

  9. #9

    Thread Starter
    Member lmstearn's Avatar
    Join Date
    Dec 2016
    Location
    Australia
    Posts
    58

    Re: StartMenu Shortcuts not Appearing from API

    Success! The "next trial" at the end of the last post produced the shortcut in the menu. Thanks all.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width