Public/Add-MSIXAppExecutionAlias.ps1
|
function Add-MSIXAppExecutionAlias { <# .SYNOPSIS Adds an App Execution Alias to an MSIX application. .DESCRIPTION Adds an App Execution Alias extension to an application entry in AppxManifest.xml. The alias lets users invoke the application by name from a Run dialog or command prompt. .PARAMETER MSIXFolder Path to the expanded MSIX package folder (must contain AppxManifest.xml). .PARAMETER MISXAppID Application/@Id value as it appears in AppxManifest.xml. .PARAMETER CommandlineAlias The alias name users type to launch the application (e.g. "WinRAR.exe"). .PARAMETER Executable Package-relative path to the executable activated by the alias (e.g. "VFS\ProgramFilesX64\WinRAR\WinRAR.exe"). When specified, it is written as the Executable attribute on the uap5:Extension element so Windows knows which process to start. Important when the Application's own Executable attribute already points to a PSF launcher. .EXAMPLE Add-MSIXAppExecutionAlias -MSIXFolder "C:\MyApp" -MISXAppID "MyAppID" -CommandlineAlias "myapp.exe" .EXAMPLE Add-MSIXAppExecutionAlias -MSIXFolder "C:\MSIXTemp\WinRAR" -MISXAppID "WinRAR" ` -CommandlineAlias "WinRAR.exe" ` -Executable "VFS\ProgramFilesX64\WinRAR\WinRAR.exe" .NOTES Author: Andreas Nick Date: 01/10/2022 https://www.nick-it.de #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)] [System.IO.DirectoryInfo] $MSIXFolder, [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 1)] [Alias('Id')] [String] $MISXAppID, [Parameter(Mandatory = $true)] [String] $CommandlineAlias, [String] $Executable = '' ) process { $manifestPath = Join-Path $MSIXFolder 'AppxManifest.xml' if (-not (Test-Path $manifestPath)) { Write-Error "AppxManifest.xml not found in: $($MSIXFolder.FullName)" return } $manifest = New-Object xml $nsmgr = New-Object System.Xml.XmlNamespaceManager $manifest.NameTable $AppXNamespaces.GetEnumerator() | ForEach-Object { $nsmgr.AddNamespace($_.Key, $_.Value) } $manifest.Load($manifestPath) $appNode = $manifest.SelectSingleNode( "//ns:Package/ns:Applications/ns:Application[@Id='$MISXAppID']", $nsmgr) if ($null -eq $appNode) { Write-Error "Application '$MISXAppID' not found in AppxManifest.xml." return } # Create Extensions element if the application has none. $extensionsNode = $appNode.SelectSingleNode('ns:Extensions', $nsmgr) if ($null -eq $extensionsNode) { $extensionsNode = $manifest.CreateElement('Extensions', $AppXNamespaces['ns']) $null = $appNode.AppendChild($extensionsNode) } # uap5 is the correct namespace for windows.appExecutionAlias per the MSIX schema. $nsUap5 = 'http://schemas.microsoft.com/appx/manifest/uap/windows10/5' $nsmgr.AddNamespace('uap5check', $nsUap5) $existingAlias = $extensionsNode.SelectSingleNode( ".//uap5check:Extension[@Category='windows.appExecutionAlias']", $nsmgr) if ($null -ne $existingAlias) { Write-Verbose "Execution alias already present for '$MISXAppID' - skipped." return } Add-MSIXManifestNamespace -Manifest $manifest -Prefixes 'uap5' Write-Verbose "Adding execution alias '$CommandlineAlias' to Application '$MISXAppID'." # Structure per MSIX schema: uap5:Extension / uap5:AppExecutionAlias / uap5:ExecutionAlias $extensionNode = $manifest.CreateElement('uap5', 'Extension', $nsUap5) $null = $extensionNode.SetAttribute('Category', 'windows.appExecutionAlias') $null = $extensionNode.SetAttribute('EntryPoint', 'Windows.FullTrustApplication') if ($Executable -ne '') { $null = $extensionNode.SetAttribute('Executable', $Executable) } $null = $extensionsNode.AppendChild($extensionNode) $aliasContainerNode = $manifest.CreateElement('uap5', 'AppExecutionAlias', $nsUap5) $null = $extensionNode.AppendChild($aliasContainerNode) $executionAliasNode = $manifest.CreateElement('uap5', 'ExecutionAlias', $nsUap5) $null = $executionAliasNode.SetAttribute('Alias', $CommandlineAlias) $null = $aliasContainerNode.AppendChild($executionAliasNode) $manifest.PreserveWhitespace = $false $manifest.Save($manifestPath) } } |