{"id":3857,"date":"2024-06-26T11:52:16","date_gmt":"2024-06-26T15:52:16","guid":{"rendered":"https:\/\/www.tmurgent.com\/TmBlog\/?p=3857"},"modified":"2024-06-26T11:52:16","modified_gmt":"2024-06-26T15:52:16","slug":"msix-shortcuts-revised","status":"publish","type":"post","link":"https:\/\/www.tmurgent.com\/TmBlog\/?p=3857","title":{"rendered":"MSIX Shortcuts Revised"},"content":{"rendered":"\n\n\n<p>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.<\/p>\n\n\n\n<p><strong>History of the source of the problems <\/strong><\/p>\n\n\n\n<p>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 &#8220;Startup&#8221; 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.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>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&#8217;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.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>Later on, Microsoft extended the AppXManifest schema with two things:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>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.<\/li>\n\n\n\n<li>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.<\/li>\n<\/ol>\n\n\n\n<p>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.<\/p>\n\n\n\n<p><strong>The dilemma<\/strong><\/p>\n<p>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.<\/p>\n<p><strong>What we learned about Desktop7 shortcut schema extension<\/strong><\/p>\n<p>Normally, in the AppXManifest any file references are listed as file paths relative to the root folder of the package.\u00a0 For example, the application executable might appear as &#8220;VFS\\ProgramFiles64\\Vendor\\App.exe&#8221;.<\/p>\n<p>The desktop 7 shortcut has two file references, one for a &#8220;File&#8221; and another optional item for an &#8220;Icon&#8221;.\u00a0 \u00a0But the file references here are quite different.\u00a0 \u00a0Here is an example from the MSIX Packaging Tool:<\/p>\n<div class=\"line\">\n<pre class=\"line\"><span class=\"html-tag\">&lt;desktop7:Extension<span class=\"html-attribute\">\u00a0<span class=\"html-attribute-name\">Category<\/span>=\"<span class=\"html-attribute-value\">windows.shortcut<\/span>\"<\/span>&gt;<\/span><br \/><br \/><\/pre>\n<div class=\"line\"><span class=\"html-tag\">&lt;desktop7:Shortcut<span class=\"html-attribute\">\u00a0<span class=\"html-attribute-name\">File<\/span>=&#8221;<span class=\"html-attribute-value\">[{Common Programs}]\\Xming\\Xming.lnk<\/span>&#8220;<\/span><span class=\"html-attribute\">\u00a0<span class=\"html-attribute-name\">Icon<\/span>=&#8221;<span class=\"html-attribute-value\">[{Package}]\\VFS\\ProgramFilesX86\\Xming\\Xming.exe<\/span>&#8220;<\/span><span class=\"html-attribute\">\u00a0<span class=\"html-attribute-name\">Arguments<\/span>=&#8221;<span class=\"html-attribute-value\">:0 -clipboard -multiwindow<\/span>&#8220;<\/span>\/&gt;<\/span><\/div>\n<pre class=\"line\"><br \/><span class=\"html-tag\">&lt;\/desktop7:Extension&gt;<\/span><\/pre>\n<\/div>\n<div>\u00a0<\/div>\n<div>We now know that this is the same format as used in the container virtual registry for values that look like file paths but applied as the equivalent relative package or VFS path.\u00a0 Thus, the File argument is the same as &#8220;VFS\\Common Programs\\Xming\\XLaunch.lnk&#8221; relative to the root of the package.<\/div>\n<div>\u00a0<\/div>\n<div>The failure we&#8217;d see when trying to install this package is due to the AppInstaller trying to read the contents of this file.\u00a0 First of all, the file must be present in the package.\u00a0 In packages captured in the MSIX Packaging Tool this is generally the case, but not so for applications converted from App-V packages by the same tool &#8211; that conversion stripped out the lnk files as not needed!\u00a0 But even if the file is present, the value of the &#8220;target&#8221; must be referenceable; the file path in the lnk file, however, would be for a native location and so when that file isn&#8217;t found the install also fails with a file not found error.\u00a0 Which is strange as the end-result doesn&#8217;t even use that target exe, it actually uses the executable listed in the parent Application record.\u00a0<\/div>\n<div>\u00a0<\/div>\n<div>Furthermore, the Microsoft Documentation for this element incorrectly describes the File parameter:<\/div>\n<pre>The path to the file that is the target of the shortcut.<br \/><br \/><\/pre>\n<p>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).\u00a0 No wonder we couldn&#8217;t get it to work!\u00a0 And to top it off the Icon can&#8217;t point to an exe\/dll to pull it from the resource section.\u00a0 But it can either be an ico or png file.<\/p>\n<p><em>By the way, I also want to caution everyone not to call these &#8220;desktop shortcuts&#8221;, as is often done in forum posts.\u00a0 This is really confusing to all of us, but especially IT folks that think of desktop shortcuts as lnk file placed on the desktop.\u00a0 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).\u00a0 So let&#8217;s all just learn to say &#8220;Desktop7 Shortcut&#8221; when referring to this.\u00a0 <\/em><\/p>\n<p><em>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.<\/em><\/p>\n<p><strong>The new solution\u00a0<\/strong><\/p>\n<p>So here is what I am doing about this now.<\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>Otherwise, when there is no PSF, we fix the desktop7 shortcut.\u00a0 This may involve creating a new lnk file and adding it into the package, but also correcting the value of the File parameter.\u00a0 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).<\/p>\n<p><strong>Bonus Fixes<\/strong><\/p>\n<p>We are also doing a better job with the VisualGroup now in TMEditX.\u00a0 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.\u00a0 If multiple levels of subfolders were used, we just consolidate using the top-level subfolder.\u00a0 If the package ends up with only one shortcut, we take the VisualGroup out since that would be simpler for the end-user.<\/p>\n<p>And while sorting all this out I found\u00a0 some edge cases of missing shell verbs (right click Edit\/Open\/etc) that also had command line arguments.\u00a0 These are now properly detected and fixed by TMEditX.<\/p>\n<div>\u00a0<\/div>\n","protected":false},"excerpt":{"rendered":"<p>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&hellip; <a class=\"more-link\" href=\"https:\/\/www.tmurgent.com\/TmBlog\/?p=3857\">Continue reading <span class=\"screen-reader-text\">MSIX Shortcuts Revised<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[53,57],"tags":[52,54,7],"class_list":["post-3857","post","type-post","status-publish","format-standard","hentry","category-msix","category-packaging","tag-msix","tag-psf","tag-tools","entry"],"_links":{"self":[{"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/posts\/3857","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3857"}],"version-history":[{"count":7,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/posts\/3857\/revisions"}],"predecessor-version":[{"id":3864,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/posts\/3857\/revisions\/3864"}],"wp:attachment":[{"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3857"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3857"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3857"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}