|
-
Dec 28th, 2018, 09:28 AM
#1
Thread Starter
Member
[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
-
Dec 28th, 2018, 08:36 PM
#2
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?
-
Dec 29th, 2018, 02:51 AM
#3
Thread Starter
Member
Re: StartMenu Shortcuts not Appearing from API
 Originally Posted by fafalone
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.
-
Dec 29th, 2018, 07:34 AM
#4
Thread Starter
Member
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
-
Dec 30th, 2018, 09:56 PM
#5
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.
-
Dec 30th, 2018, 10:26 PM
#6
Re: StartMenu Shortcuts not Appearing from API
I seriously doubt that Windows Search plays any role here.
-
Dec 30th, 2018, 10:47 PM
#7
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.
-
Dec 31st, 2018, 07:54 AM
#8
Thread Starter
Member
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
-
Jan 1st, 2019, 12:21 AM
#9
Thread Starter
Member
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|