{"id":4105,"date":"2025-11-13T15:32:14","date_gmt":"2025-11-13T20:32:14","guid":{"rendered":"https:\/\/www.tmurgent.com\/TmBlog\/?p=4105"},"modified":"2025-11-13T15:32:14","modified_gmt":"2025-11-13T20:32:14","slug":"how-an-empty-msix-package-saved-the-day-on-24h2","status":"publish","type":"post","link":"https:\/\/www.tmurgent.com\/TmBlog\/?p=4105","title":{"rendered":"How an empty MSIX package saved the day on 24H2"},"content":{"rendered":"\n<p>This is a story about a native windows application installer that needed MSIX to help it work right.\u00a0 And a story about how the App-V package of that app needed MSIX to help it work right.\u00a0 And yes, also a story about how the MSIX package of that app works just right.\u00a0<\/p>\n<p>Let&#8217;s learn about the Shell extension context menu handler hell, our good friend, Notepad++, and a previously uncovered feature of MSIX that saves the day!<\/p>\n<h4>Backstory about Shell Extension Context Menus<\/h4>\n<p>There are (at least) three ways that an application can add right-click menus to files of certain types into the Windows explorer.<\/p>\n<ul>\n<li><strong>Shell Integration Verb<\/strong> <strong>Commands<\/strong>. The application installer registers hard-coded menu item names and the command to run under a key named &#8220;Shell&#8221; under the filetype (or a ProgId pointed to by the filetype) in the windows registry classes key.\u00a0 \u00a0The Windows Explorer process will consult the registry and add these items to the popup list when the user right-clicks on a file of this type. This method has been in Windows for a long as anyone can remember; <em>it is older than dirt<\/em>.<\/li>\n<li><strong>Shell Extension Context Menu Handler.<\/strong> The application installer adds a COM In-Process dll that internally implements the IContext interface and registers it under the ShellEx key of the filetype\/progid.\u00a0 This is sometimes referred to as the &#8220;traditional&#8221; or &#8220;legacy&#8221; version of the context menu handler. The Windows explorer will call this shell extension handler and ask it which menu items to add.\u00a0 This makes the list more dynamic as the handler can choose to look at the situation and offer different items for different situations.\u00a0 This method has also been around in Windows a really long time; <em>it is as old as dirt<\/em>.<\/li>\n<li><strong>Shell Context Menu Command Handler.<\/strong> The application installer adds a COM In-Process dll that internally implements the IExplorerCommand interface and registers it under the Shell key of the filetype\/progid, but using a registry item named ExplorerCommandHandler.\u00a0 This is sometimes referred to as the &#8220;Modern&#8221; version of the context menu handler.\u00a0 Like the traditional handler, this interface is called by Windows Explorer and asks which menus to add to the right click of the file.\u00a0It has only been around since Windows Vista.\u00a0 <em>Just a young puppy by Windows standards<\/em>.\u00a0<\/li>\n<\/ul>\n<h4>Backstory about Notepad++<\/h4>\n<p>Notepad++ is a free XML file editor program for Windows that is available on the internet.\u00a0 <em>It has been around a long time<\/em>, we aren&#8217;t sure how long but probably before Windows Vista.<\/p>\n<p>Notepad++ originally implemented the Shell Extension Context Menu Handler iContext interface.\u00a0 In fact, most Windows software products that add a context menu use the traditional type of handler for this purpose.<\/p>\n<p>At some point, Notepad++ switched over to the newer Shell Context Menu Command Handler iExplorerCommand interface.\u00a0 We don&#8217;t see a lot of apps doing this.<\/p>\n<p>The odd thing is that, as far as we know, the result returned by the handler is always the same &#8211; it really isn&#8217;t dynamic.\u00a0 It always seems to just adds an entry to the list that says &#8220;Open in Notepad++&#8221; when the right click occurs.\u00a0 It also registers this to all file types, using the Classes\\* key to register its shell extension.\u00a0 I mean, it could have been just a simple Shell verb!\u00a0\u00a0<\/p>\n<p>More recently, the developer decided to take on the mess that Microsoft created in Windows 11 with right clicks.\u00a0 Their IExplorerCommand added menus were not appearing directly on the menu seen when you right-click.\u00a0 Instead, you had to select the &#8220;Show more options&#8221; item to see the full list (or hold the shift key when you right-click &#8211; something few people know to do).<\/p>\n<p>When the installer runs, it adds the files to the system.\u00a0 In addition to the main program, this includes these two files in a subfolder.<\/p>\n<div>\n<p><img decoding=\"async\" class=\"alignleft size-medium wp-image-4116\" src=\"https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_Files-300x97.jpg\" alt=\"\" width=\"100%\" srcset=\"https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_Files-300x97.jpg 300w, https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_Files-768x248.jpg 768w, https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_Files.jpg 792w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/p>\n<\/div>\n<p>The dll is the file that implements the context menu.\u00a0 The second is the msix package to be used in the installation later.<\/p>\n<p>The installer next calls rundll32.exe against the NppShell.dll file that is the modern context menu handler implementation using the Shell and ExplorerCommandHandler item:<\/p>\n<div>\n<p><img decoding=\"async\" class=\"alignleft size-medium wp-image-4110\" src=\"https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_SHex_RunDll-300x166.jpg\" alt=\"\" width=\"100%\" srcset=\"https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_SHex_RunDll-300x166.jpg 300w, https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_SHex_RunDll-768x425.jpg 768w, https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_SHex_RunDll.jpg 786w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/p>\n<\/div>\n<p>The rundll32 command also registered the COM CLSID as shown here:<\/p>\n<div>\n<p><img decoding=\"async\" class=\"alignleft size-medium wp-image-4115\" src=\"https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_SHex_Clsid-300x51.jpg\" alt=\"\" width=\"100%\" srcset=\"https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_SHex_Clsid-300x51.jpg 300w, https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_SHex_Clsid-768x129.jpg 768w, https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_SHex_Clsid.jpg 843w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/p>\n<\/div>\n<p>These are the kind of registrations that a natively installed program would normally do.<\/p>\n<p><strong>But they also have this small MSIX package inside their traditional exe installation program.<\/strong>\u00a0 \u00a0I have previously written about this in a blog post two years ago when attempting to re-package the entire application into an MSIX package:\u00a0<a href=\"https:\/\/www.tmurgent.com\/TmBlog\/?p=3643\">The Strange New Twists in Notepad++ Context Menu \u2013 Confessions of a Guru<\/a> , although at the time I really didn&#8217;t understand why the developer did this.<\/p>\n<p>My MSIX solution was to add detection of these new type of registry entries created by Rundll32 (which I had never seen before) into TMEditX and fix up the AppXManifest file to use the desktop4:FileExplorerContextMenu element for &#8220;modern&#8221; context menus.\u00a0 This is seamless and easy for repackaging into MSIX as it is an automatic default fixup in TMEditX. In essence, this means adding the same two applications extensions seen in the vendor msix package AppXManifest file here:<\/p>\n<div>\n<p><img decoding=\"async\" class=\"alignleft size-medium wp-image-4118\" src=\"https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_MsixManifest-300x194.jpg\" alt=\"\" width=\"100%\" srcset=\"https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_MsixManifest-300x194.jpg 300w, https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_MsixManifest-1024x662.jpg 1024w, https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_MsixManifest-768x496.jpg 768w, https:\/\/www.tmurgent.com\/TmBlog\/wp-content\/uploads\/2025\/11\/NPP_MsixManifest.jpg 1233w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/p>\n<\/div>\n<p>When this is vendor MSIX package installed by the native vendor exe installer into the system, there is now also a &#8220;PackagedCom&#8221; registration that can be seen in the registry.\u00a0 But previously I never understood how that vendor worked with the natively installed application until I was called up by a customer in Germany with an App-V problem involving this application.<\/p>\n<h4>The App-V issue<\/h4>\n<p>Many years ago, App-V had a well-known solution for the original context menu handler that required no special effort for someone repackaging Notepad++ with the old-schoolShell Extension Context Menu Handler with the IContext interface.\u00a0 You just repackaged it, and it was fine with no special steps needed.\u00a0<\/p>\n<p>App-V packagers also developed a solution to manually handle Notepad++ with the Shell Context Menu Handler with the IExplorerCommand interface.\u00a0 This typically involved an App-V package Publishing script to run regsvr32.exe against the context menu handler dll so that it was natively added to the registry.\u00a0 A tad ugly, but got the job done.<\/p>\n<p>Then comes changes that Microsoft made in Windows 24H2.\u00a0 This messed up the App-V solution.\u00a0 A customer asked, so I looked into this further.<\/p>\n<h4>What was this magic MSIX package?<\/h4>\n<p>The MSIX package that the installer added was not a typical MSIX package.\u00a0 It contains no files that are part of the package!\u00a0 It is a &#8220;sparse package&#8221;, which is one that references files that are not part of the package.\u00a0 The vendor exe installer places this msix file right next to the dll which holds the context menu handler implementation.\u00a0 I did not understand the significance of this when I was looking to create a full MSIX package since we discard their msix file.<\/p>\n<p>Investigating further for the App-V issue, I found that the package declares the <strong>capability &#8220;UnvirtualizedResources&#8221;<\/strong>, which, it turns out, allows the package AppXManifest.xml file to reference files that are not part of the package.\u00a0 Normally this is not possible, which is why I never understood that package. I previously uncovered this capability as also being needed for the unrelated &#8220;Flexible Virtualization&#8221; (See <a href=\"https:\/\/www.tmurgent.com\/appv\/images\/WhitePapers\/FlexibleVirtualization.pdf\">White Paper FileSystemWriteVirtualization<\/a>\u00a0and <a href=\"https:\/\/www.tmurgent.com\/TmBlog\/?p=4087\">Blog RegistryWriteVirtualization<\/a>) features, but never made the connection to this usage.<\/p>\n<p>This vendor msix package appears to exist only for the purpose of adding the modern shell extension using the desktop4:FIleExplorerContextMenu element, along with the com:comserver element for the CLSID.\u00a0 These elements reference the name of the dll as a relative file, and if the file was in the root of the package then the UnvirtualizedResources capability would not have been needed.<\/p>\n<p>But instead, the vendor exe installer uses a trick when installing the package to tell the package what folder the dll will be in.\u00a0 Although we think that the installer uses the PackageManager interface, the equivalent for the PowerShell command to add the argument <strong>-ExternalLocation &lt;URI&gt;<\/strong> to the Add-AppXPackage command, where &lt;URI&gt; is the folder where the exe installer placed the dll (by default under &#8220;C:\\Program Files\\Notepad++\\contextMenu&#8221;.\u00a0 This trick makes the relative path to the file found in the AppXManifest file work when Windows Explorer sees the right click.<\/p>\n<p>By installing the context menu handler this modern package way, the traditional installer get a right-click menu that appears like it used to before Microsoft messed things up. (I&#8217;m sure that someone from Microsoft would argue that it was for a good reason, but I am not listening&#8230;).\u00a0 Even when the installation is a traditional exe installation.<\/p>\n<p>So, what does this mean for the App-V packaging?\u00a0 Well, it means that we can repackage into App-V and add a simple ps1 file into the folder that contains the dll and msix file.\u00a0 We change our recipe to have the Publish script call this PowerShell file.<\/p>\n<p>So what does the PowerShell file do?\u00a0 It calls get-appvclientpackage against the known name of the package &#8220;Notepad XXX&#8221;, extracts the installation location of the App-V package from the returned object, which of course is not under C:\\ProgramData\\AppV and guids.\u00a0 It then runs the command Add-AppXPackage -ExternalLocation &#8220;&lt;folder&gt;\\VFS\\ProgramFilesX64\\Notepad++\\contextMenu&#8221; &#8220;&lt;folder&gt;\\VFS\\ProgramFilesX64\\Notepad++\\contextMenu\\NppShell.msix&#8221; where &lt;folder&gt; is the returned installation location of the App-V package.\u00a0 For example, if the App-V package name was &#8220;NPP&#8221;:<\/p>\n\n\n\n<table style=\"border-collapse: collapse; width: 100%; font-size: 12px; background: white;\">\n<tbody>\n<tr>\n<td style=\"width: 100%;\">\n<p><span style=\"color: #000000;\">$InsidePath = &#8220;VFS\\ProgramFIlesX64\\Notepad++\\contextMenu&#8221;<br \/>$appvPkg = get-AppvClientPackage &#8220;NPP&#8221;<br \/>Add-AppxPackage -ExternalLocation &#8220;$appVPkg\\$InsidePath&#8221; &#8220;$appVPkg\\$InsidePath\\NppShell.msix&#8221;&nbsp;<\/span><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n\n\n<p>The customer reports that the App-V package now works as expected, and we learn a new trick for MSIX packages that will probably come in handy for other things.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a story about a native windows application installer that needed MSIX to help it work right.\u00a0 And a story about how the App-V package of that app needed MSIX to help it work right.\u00a0 And yes, also a story about how the MSIX package of that app works just right.\u00a0 Let&#8217;s learn about&hellip; <a class=\"more-link\" href=\"https:\/\/www.tmurgent.com\/TmBlog\/?p=4105\">Continue reading <span class=\"screen-reader-text\">How an empty MSIX package saved the day on 24H2<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[47,53,57],"tags":[33,73,52],"class_list":["post-4105","post","type-post","status-publish","format-standard","hentry","category-appv5","category-msix","category-packaging","tag-appv","tag-context-menu","tag-msix","entry"],"_links":{"self":[{"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/posts\/4105","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=4105"}],"version-history":[{"count":13,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/posts\/4105\/revisions"}],"predecessor-version":[{"id":4127,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=\/wp\/v2\/posts\/4105\/revisions\/4127"}],"wp:attachment":[{"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4105"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4105"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tmurgent.com\/TmBlog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4105"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}