This post will help you add desktop shortcuts to your MSIX packaged applications. Currently there is no built-in support in the MSIX Packaging Tool to carry over desktop shortcuts you may have defined in your MSI or setup.exe.
The approach here will use a PowerShell script (CreateShortcuts.ps1
) to create shortcuts on the users desktop when the app is run for the first time. It requires updating the Appxmanifest.xml
file and adding Package Support Framework (PSF) support to the MSIX package. It does not require any existing shortcut (.lnk
) files or applications icons (.ico
).
You'll need the following:
CreateShortcuts.ps1
. Clone this repository: https://github.com/mjfusa/msix-create-desktop-shortcuts. The script is in the ScriptInPackage
folder.
# PowerShell - Download PsdBinaries 2.0 into the PsfBinaries folder
md PsfBinaires
cd PsfBinaires
wget https://github.com/microsoft/MSIX-PackageSupportFramework/releases/download/v2.0/PSFBinaries.zip -OutFile PSFBinaries.zip
Expand-Archive .\PSFBinaries.zip
You will need to start with an existing MSIX packaged app.
Extract the contents of your MSIX package to a temporary directory. You can use the MSIX Packaging Tool
to do this.
Change to the temporary directory to where you unpackaged the application.
Run the script CreateManifestAndConfigForPSF.ps1
in the same folder where you have saved the extracted the application.
After running the script, the icon(s) are extracted, converted to ico files and saved to the 'Icons' folder. Also AppxmanifestNew.xml
and config.json
are created. config.json
is required by the Package Support Framework. You will replace the existing manifest with the contents of AppxmanifestNew.xml
.
Open your MSIX package for editing in the MSIX Packaging tool (MPT)
In the 'Manifest file' section click on 'Open File'. The manifest will be opened into Notepad for editing.
Open AppmanifestNew.xml
created in the section above in another editor and copy the entire contents to the clipboard.
Go back Notepad. Delete all of the contents and paste in the contents you copied in the previous step.
Notepad should now have the contents of AppmanifestNew.xml
. Save the file and close notepad.
Verify in MPT that you have no errors in the 'Manifest file' section.
See the How it works section for information on what is changed in the manifest.
Click on 'Package files' in MPT
Right click on Package
Click Add File
and add the config.json
file that was created in the Create Icons, AppxmanifestNew.xml and config section above.
Click on 'Package files' in MPT
Right click on Package
Click on New folder
. Type Icons
. Click Save
Right click on Icons
Click Add File
and add the ico files that were created in the section Create Icons, AppxmanifestNew.xml and config above.
CreateShortcuts.ps1
scriptNote: For this step you will need the PSF Binaries and the CreateShortcuts.ps1
script included in the GitHub repository. See Prerequisites.
Go back to MPT
Click on 'Package files' in MPT
Right click on Package
Click 'Add File' and add the following files from the PSFBinaries\bin
folder:
PsfLauncher32.exe
PsfLauncher64.exe
PsfRunDll32.exe
PsfRunDll64.exe
PsfRuntime32.dll
PsfRuntime64.dll
StartingScriptWrapper.ps1
The StartingScriptWrapper.ps1
is required to run PowerShell scripts from PSF.
CreateShortcuts.ps1
Package
CreateShortcuts.ps1.
The script is in the ScriptInPackage folder in the clone repository. See prerequisties.After adding the Icons
, CreateShortcuts.ps1
, PsfBinaries
and StartingScriptWrapper.ps1
, the Package files section in MPT should look like this:
You have added all of the necessary files and can now save and sign the MSIX.
CreateManifestAndConfigForPSF.ps1
)CreateManifestAndConfigForPSF.ps1
scans the manifest file for the App Ids, display name and app description for displaying in the shortcut. For example:
<Application Id="App" . . . >
<uap:VisualElements DisplayName="Hello MSIX World" Description="This app displays Hello World and the app version" . . . />
</uap:VisualElements>
The script will skip the applications that have the attribute AppListEntry="none"
as these are not displayed in the Start menu.
The following changes are made to the manifest file:
<Application Id="App" Executable="HelloWpf\HelloWpf.exe" EntryPoint="Windows.FullTrustApplication">
is replaced with:
<Application Id="App" Executable="psflauncher64.exe" EntryPoint="Windows.FullTrustApplication">
The app architecture is determined by the ProcessorArchitecture setting in the Identity node of the manifest. For example:
<Identity Name="Hello.MSIX.World" Publisher="CN=@MikeFrancis" Version="1.0.0.0" ProcessorArchitecture="x64" />
Shortcuts work by providing a path to an executable's EXE. Since the path to an MSIX packaged EXE is not accessible, we need to define an alias which the shortcut will use to launch the app.
The script will define an alias in the Appmanifest.xml. For example:
<Extensions>
<uap3:Extension Category="windows.appExecutionAlias" Executable="HelloWpf\HelloWpf.exe" EntryPoint="Windows.FullTrustApplication">
<uap3:AppExecutionAlias>
<desktop:ExecutionAlias Alias="hellowpf.exe" />
</uap3:AppExecutionAlias>
</uap3:Extension>
</Extensions>
<!-- The app will launch when 'hellowpf.exe' is entered on the command line - as if it were in the users PATH -->
The script will also include the additional schema references (uap3 and desktop) as needed by the AppExecutionAlias.
CreateManifestAndConfigForPSF.ps1
collected the Executable paths and App Ids from the Appxmanifest.xml
. These values are used to create the config.json
file.
The ico files are copied from the Images
folder (see section Icons) to the $env:APPDATA
folder. The shortcut references the icon from this folder.
CreateShortcuts.ps1
)When the user clicks on the app icon in the Start menu, PsfLauncher*.exe starts. It loads config.json
which contains the script to run - in this case CreateShortcuts.ps1
. After the script runs, the app HelloWpf\HelloWpf.exe is launched. The script will only run when the app is launched the first time. See here for the full list of config.json
settings:
config.json
{
"applications": [
{ "startScript": {
"scriptPath": "CreateShortcuts.ps1"
},
"arguments": "",
"id": "App",
"executable": "HelloWpf\\HelloWpf.exe"
}
]
}
The shortcuts are created calling the Windows Script Host class methods to create the shortcuts. Here is the relevant code in CreateShortcuts.ps1
:
$WshShell = New-Object -comObject WScript.Shell
$lnkPath = ($destinationDesktopPath + "\" + $app.DisplayName + ".lnk")
$Shortcut = $WshShell.CreateShortcut($lnkPath)
$Shortcut.TargetPath = $(Split-Path $app.Executable -Leaf)
$Shortcut.IconLocation = ($env:APPDATA + "\" + $app.DisplayName + ".ico")
$Shortcut.WorkingDirectory = ($ENV:LOCALAPPDATA + "\Microsoft\WindowsApps")
$Shortcut.Description = ($app.Description)
$Shortcut.Save()
Note that $Shortcut.IconLocation
requires an .ico
file. This is created by extracting the icon from the EXE and then bitmap and conversion Win32 APIs are used to create the .ico
file. The icons are created by the CreateManifestAndConfigForPSF.ps1 script - see the section 'Create Icons, AppxmanifestNew.xml and config.json' above.
The key functions are:
System.Drawing.Bitmap.Save(mem_data, System.Drawing.Imaging.ImageFormat.Png);
This uses the feature of PowerShell that can interpret C# code! Credit: Crissy LeMaire for the C# / PowerShell Icon Extraction code.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.