These last couple of weeks I have been busy researching into problems some customers were having with MSIX packages with shortcuts. This post will bring you up to date on some new information on how MSIX works, and details on how TMEditX is changing handling these issues starting in version 4.6.
History of the source of the problems
Traditionally applications created shortcuts by dropping a lnk file in one of the start menus (one per-machine and one per-user). The lnk file contains a target executable with optional command line arguments, and optionally a working directory and icon. Items could be grouped into subfolders (and even multiple level subfolders). And there is a special start menu folder called “Startup” which is a place for apps that should launch automatically when the user logs in (one of several techniques to do this). The explorer process that runs your desktop was responsible to monitor these locations and provide the start menu.
Oh, and the app installer could also drop them on the desktop, although in deploying apps in the enterprise we usually want to remove the desktop shortcuts.
In MSIX, those are converted into entries in the AppXManifest. While the original lnk files might be left in the package, these are not consulted and the AppXManifest entries are used when the package is installed to add things into the start menu.
Early on in MSIX there were a lot of restrictions on what could be in the AppXManifest to generate entries into the start menu. Any given exe file in the package was limited to only one start menu entry, and it couldn’t have any command line arguments. The xml element used to contain this was part of the Uap2 schema extension and called VisualElements; this was placed as a child of the Application element pointing to the exe to run.
To get around some of the limitations, we often used the Package Support Framework. A copy of PsfLauncher.exe could be added to the package for each shortcut we wanted, and the PSF config.json file would identify the exe to be run, the arguments, and the working directory.
Later on, Microsoft extended the AppXManifest schema with two things:
- Microsoft created a new Uap3 schema extension for VisualElements which added a new parameter for the start menu folder, called VisualGroup. With this you can add a single level folder to group the start menu items in this package under.
- Microsoft later created a new Desktop7 schema extension. This schema extension may also be added as a child of the Application, and it may contain multiple desktop7:shortcut elements, each of which can have different shortcut names, arguments, and icons.
In late 2022, Microsoft changed the MSIX Packaging tool to start adding these into captured packages, but they did not work, and we routinely removed them when fixing up the packages.
The dilemma
Removing the desktop7 shortcut element solved the problem of not being able to install the packages, but it meant that we had to rely on the PSF to get multiple shortcuts to the same program and for command line arguments.
What we learned about Desktop7 shortcut schema extension
Normally, in the AppXManifest any file references are listed as file paths relative to the root folder of the package. For example, the application executable might appear as “VFS\ProgramFiles64\Vendor\App.exe”.
The desktop 7 shortcut has two file references, one for a “File” and another optional item for an “Icon”. But the file references here are quite different. Here is an example from the MSIX Packaging Tool:
<desktop7:Extension Category="windows.shortcut">
</desktop7:Extension>
The path to the file that is the target of the shortcut.
Add to this forum posts by Microsoft employees showing examples where the value of the File parameter was directly an exe (when it must be a lnk file). No wonder we couldn’t get it to work! And to top it off the Icon can’t point to an exe/dll to pull it from the resource section. But it can either be an ico or png file.
By the way, I also want to caution everyone not to call these “desktop shortcuts”, as is often done in forum posts. This is really confusing to all of us, but especially IT folks that think of desktop shortcuts as lnk file placed on the desktop. The desktop in this schema extension means that the extension is intended only for packages installed on Windows, as opposed to UWP apps or Maui (the newer multiple platform solution for developers). So let’s all just learn to say “Desktop7 Shortcut” when referring to this.
MSIX does not have any support that you can add to the package to cause a desktop shortcut to be added upon installation of the package! And we also get asked about this quite a bit.
The new solution
So here is what I am doing about this now.
If the application has multiple shortcuts to the same exe, we will always inject the PSF and remove the desktop7 shortcut element. This injection will add copies so that each application element creates only one start menu entry, via the VisualElements element.
Otherwise, when there were not multiple shortcuts to the same exe, if we have other reasons to add the PSF, we similarly get rid of the desktop7 shortcut element.
Otherwise, when there is no PSF, we fix the desktop7 shortcut. This may involve creating a new lnk file and adding it into the package, but also correcting the value of the File parameter. We also replace the Icon reference by pointing to the same PNG file as in the Application element (just changing the reference into this Registry format).
Bonus Fixes
We are also doing a better job with the VisualGroup now in TMEditX. If we detect that the original shortcuts used a subfolder, or if the lnk was missing but the incorrect File reference indicated a subfolder, then we add the VisualGroup. If multiple levels of subfolders were used, we just consolidate using the top-level subfolder. If the package ends up with only one shortcut, we take the VisualGroup out since that would be simpler for the end-user.
And while sorting all this out I found some edge cases of missing shell verbs (right click Edit/Open/etc) that also had command line arguments. These are now properly detected and fixed by TMEditX.