Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
4de4758
fix wrong variable quoting in file path command
KernelGhost Jul 31, 2025
078c9b0
Merge pull request #2 from KernelGhost/codex/find-and-fix-critical-bu…
KernelGhost Jul 31, 2025
6e9e633
Fix typo in EC_NO_SUDO comment
KernelGhost Jul 31, 2025
ba2ec0a
fix spacing for Shortcut Name comments
KernelGhost Jul 31, 2025
4b4fe93
Merge pull request #3 from KernelGhost/codex/fix-typo-in-setup.sh-com…
KernelGhost Jul 31, 2025
82b4d8b
Merge pull request #4 from KernelGhost/codex/update-shortcut-name-in-…
KernelGhost Jul 31, 2025
4136b1d
fix spelling
KernelGhost Jul 31, 2025
0f3b43d
fix typo in PrintArrayData parameter comment
KernelGhost Jul 31, 2025
1c79a78
docs: fix typo in libvirt CPU pinning section
KernelGhost Jul 31, 2025
e4d4b91
Fix User Agent Switcher instructions
KernelGhost Jul 31, 2025
e62155c
fix: correct user source path comment
KernelGhost Jul 31, 2025
c6a8a43
Merge pull request #8 from KernelGhost/codex/update-wording-in-readme.md
KernelGhost Jul 31, 2025
2f184cb
Merge pull request #6 from KernelGhost/codex/fix-typo-in-extractprogr…
KernelGhost Jul 31, 2025
12530a6
Merge pull request #5 from KernelGhost/codex/fix-typo-in-readme.md
KernelGhost Jul 31, 2025
f1441a5
Merge pull request #7 from KernelGhost/codex/fix-typo-in-cpu-pinning-…
KernelGhost Jul 31, 2025
26854d9
fix erroneous change by Codex
KernelGhost Jul 31, 2025
9c0564c
Merge pull request #9 from KernelGhost/codex/update-user_source_path-…
KernelGhost Jul 31, 2025
a23fd71
Fix disk mapping example
KernelGhost Aug 1, 2025
cc13aac
docs: fix grammar in docker instructions
KernelGhost Aug 1, 2025
8cac5af
docs: fix grammar in detected file comment
KernelGhost Aug 1, 2025
708ad60
fix script conditional
KernelGhost Aug 1, 2025
e5d6f60
Merge pull request #13 from KernelGhost/codex/edit-install.bat-to-fix…
KernelGhost Aug 1, 2025
3ea6c61
Merge pull request #12 from KernelGhost/codex/update-comment-in-setup.sh
KernelGhost Aug 1, 2025
050384d
Merge pull request #11 from KernelGhost/codex/edit-docker.md-for-word…
KernelGhost Aug 1, 2025
ff0cef7
Merge pull request #10 from KernelGhost/codex/update-disk-mapping-exa…
KernelGhost Aug 1, 2025
92686f0
Fix grammar in license
KernelGhost Aug 1, 2025
f0aa7d6
docs: clarify removable media comment
KernelGhost Aug 1, 2025
7abe89e
Merge pull request #14 from KernelGhost/codex/edit-license.md-for-gra…
KernelGhost Aug 1, 2025
bbf2da8
Merge pull request #15 from KernelGhost/codex/update-comment-for-wafi…
KernelGhost Aug 1, 2025
fdecd7a
clarified shutdown error text
KernelGhost Aug 1, 2025
e803794
various improvements to install.bat
KernelGhost Aug 1, 2025
6a7b57a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 1, 2025
a04103b
fix: use string compare for path check
KernelGhost Aug 1, 2025
ab496b9
Merge pull request #16 from KernelGhost/codex/replace-numeric-compari…
KernelGhost Aug 1, 2025
88f1e4e
Update ExtractPrograms.ps1
KernelGhost Aug 2, 2025
c25ea7c
integrate libvirtd group support + document in install guide + remove…
KernelGhost Aug 2, 2025
887e282
remove '.DS_Store' files + update gitignore
KernelGhost Aug 2, 2025
44f9df7
update setup.patch to match change in 9c0564cca429d1f4eb181643dab4844…
KernelGhost Aug 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/.idea
/.vscode
/result
.DS_Store
**/.DS_Store
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Due to lack of a license, it is All Rights Reserved by the original author.
We have tried contacting Fmstrat about this, but they abandoned the project and did not reply nor apply an open-source license to the project.
However, almost all parts of the codebase have been rewritten and all new contributions require a Contributor License Agreement ([for individuals](https://gist.github.com/oskardotglobal/35f0a72eb45fcc7087e535561383dbc5), [for legal entities](https://gist.github.com/oskardotglobal/75a8cc056e56a439fa6a1551129ae47f)) to be signed. Therefore, the below license is applied to all new contributions made to the project.

Refer to a specific file for it's respective license.
Refer to a specific file for its respective license.

# GNU AFFERO GENERAL PUBLIC LICENSE

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ WinApps works by:
- The GNU/Linux `/home` directory is accessible within Windows via the `\\tsclient\home` mount.
- Integration with `Nautilus`, allowing you to right-click files to open them with specific Windows applications based on the file MIME type.
- The [official taskbar widget](https://github.com/winapps-org/WinApps-Launcher) enables seamless administration of the Windows subsystem and offers an easy way to launch Windows applications.
- Microsoft Office links (e.g. ms-word://) from the host system are automatically opened in the Windows subsystem. (Note: You may need to use an [User Agent switcher](https://github.com/ray-lothian/UserAgent-Switcher/) Browser Extension and set the User-Agent to Windows, as as the Office webapps typically hide the "Open in Desktop App" option for Linux users.)
- Microsoft Office links (e.g. ms-word://) from the host system are automatically opened in the Windows subsystem. (Note: You may need to use a [User Agent Switcher](https://github.com/ray-lothian/UserAgent-Switcher/) browser extension and set the User-Agent to Windows, as the Office webapps typically hide the "Open in Desktop App" option for Linux users.)

## Supported Applications
**WinApps supports <u>*ALL*</u> Windows applications.**
Expand Down Expand Up @@ -398,7 +398,7 @@ RDP_SCALE="100"
# This improves compatibility with most desktop environments (DEs).
# ATTENTION: The Filesystem Hierarchy Standard (FHS) recommends /media instead. Verify your system's configuration.
# - To manually mount devices, you may optionally use /mnt.
# REFERRENCE: https://wiki.archlinux.org/title/Udisks#Mount_to_/media
# REFERENCE: https://wiki.archlinux.org/title/Udisks#Mount_to_/media
REMOVABLE_MEDIA="/run/media"

# [ADDITIONAL FREERDP FLAGS & ARGUMENTS]
Expand Down
15 changes: 8 additions & 7 deletions bin/winapps
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,15 @@ Please run:
notify-send --expire-time=8000 --icon="dialog-error" --app-name="WinApps" --urgency="low" "WinApps" "Windows failed to resume."
;;
"$EC_FAIL_DESTROY")
dprint "ERROR: WINDOWS FAILED TO IMMEDIATELY UNGRACEFULLY SHUT DOWN WINDOWS. EXITING."
notify-send --expire-time=8000 --icon="dialog-error" --app-name="WinApps" --urgency="low" "WinApps" "Failed to ungracefully shut down Windows."
dprint "ERROR: FAILED TO FORCE STOP WINDOWS. EXITING."
notify-send --expire-time=8000 --icon="dialog-error" --app-name="WinApps" --urgency="low" "WinApps" "Failed to forcibly stop Windows."
;;
"$EC_SD_TIMEOUT")
dprint "ERROR: WINDOWS TOOK TOO LONG TO SHUT DOWN. EXITING."
notify-send --expire-time=8000 --icon="dialog-error" --app-name="WinApps" --urgency="low" "WinApps" "Windows took too long to shut down."
;;
"$EC_DIE_TIMEOUT")
dprint "ERROR: WINDOWS TOOK TOO LONG TO SHUT DOWN. EXITING."
dprint "ERROR: WINDOWS TOOK TOO LONG TO DIE. EXITING."
notify-send --expire-time=8000 --icon="dialog-error" --app-name="WinApps" --urgency="low" "WinApps" "Windows took too long to die."
;;
"$EC_RESTART_TIMEOUT")
Expand Down Expand Up @@ -158,7 +158,7 @@ function dprint() {
[ "$DEBUG" = "true" ] && echo "[$(date)-$RUNID] $1" >>"$LOG_PATH"
}
# Name: 'waFixRemovableMedia'
# Role: If user left REMOVABLE_MEDIA config null,fallback to /run/media for udisks defaults ,warning.
# Role: If REMOVABLE_MEDIA is empty, default to /run/media (udisks default) and show a warning.
function waFixRemovableMedia() {
if [ -z "$REMOVABLE_MEDIA" ]; then
REMOVABLE_MEDIA="/run/media" # Default for udisks
Expand Down Expand Up @@ -301,9 +301,10 @@ function waGetFreeRDPCommand() {
function waCheckGroupMembership() {
# Identify groups the current user belongs to.
# shellcheck disable=SC2155 # Silence warnings regarding masking return values through simultaneous declaration and assignment.
local USER_GROUPS=$(groups "$(whoami)")
local USER_GROUPS=$(id -nG "$(whoami)")

if ! (echo "$USER_GROUPS" | grep -q -E "\blibvirt\b") || ! (echo "$USER_GROUPS" | grep -q -E "\bkvm\b"); then
if ! echo "$USER_GROUPS" | grep -qE '\b(libvirt|libvirtd)\b' || \
! echo "$USER_GROUPS" | grep -qE '\bkvm\b'; then
waThrowExit "$EC_NOT_IN_GROUP"
fi
}
Expand Down Expand Up @@ -677,7 +678,7 @@ function waRunCommand() {
+auto-reconnect \
/drive:media,"$REMOVABLE_MEDIA" \
/wm-class:"$FULL_NAME" \
/app:program:"$WIN_EXECUTABLE",icon:"$ICON",name:$"FULL_NAME",cmd:\""$FILE_PATH"\" \
/app:program:"$WIN_EXECUTABLE",icon:"$ICON",name:"$FULL_NAME",cmd:\""$FILE_PATH"\" \
/v:"$RDP_IP" &>/dev/null &

# Capture the process ID.
Expand Down
2 changes: 1 addition & 1 deletion compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ services:
# NOTE: 'disk1' will be mounted as the main drive. THIS DISK WILL BE FORMATTED BY DOCKER.
# All following disks (disk2, ...) WILL NOT BE FORMATTED.
# - /dev/disk/by-id/<id>:/disk1
# - dev/disk/by-id/<id>:/disk2
# - /dev/disk/by-id/<id>:/disk2
# group_add: # uncomment this line and the next one for using rootless podman containers
# - keep-groups # to make /dev/kvm work with podman. needs "crun" installed, "runc" will not work! Add your user to the 'kvm' group or another that can access /dev/kvm.
4 changes: 2 additions & 2 deletions docs/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ Although WinApps supports using `QEMU+KVM+libvirt` as a backend for running Wind

> [!IMPORTANT]
> The iptables kernel module must be loaded for folder sharing with the host to work.
> Check that the output of `lsmod | grep ip_tables` and `lsmod | grep iptable_nat` is non empty.
> If the output of one of the previous command is empty, run `echo -e "ip_tables\niptable_nat" | sudo tee /etc/modules-load.d/iptables.conf` and reboot.
> Check that the output of `lsmod | grep ip_tables` and `lsmod | grep iptable_nat` is non-empty.
> If the output of one of the previous commands is empty, run `echo -e "ip_tables\niptable_nat" | sudo tee /etc/modules-load.d/iptables.conf` and reboot.

## `Docker`
### Installation
Expand Down
4 changes: 3 additions & 1 deletion docs/libvirt.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ Together, these components form a powerful and flexible virtualization stack, wi
sudo reboot # Reboot the system to ensure the user is added to the relevant groups.
```

Note: On NixOS, the group name for libvirt is `libvirtd` and not `libvirt`. In addition, user and group management on NixOS is handled through the Nix configuration files and not via traditional tools like `usermod`. Please see "Adding User to a group" on [this NixOS Wiki page](https://wiki.nixos.org/wiki/User_management).

Note: Due to a known bug in `rpm-ostree`, which affects various distributions such as Silverblue, Bazzite, Bluefin, Kinoite, Aurora, UCore, and others, the commands provided earlier may not properly add your user to all required groups. If the `groups $USER` command does not show your user as being part of the necessary groups, you'll need to manually add these groups to `/etc/group` if they are present in `/usr/lib/group`.

To resolve this:
Expand Down Expand Up @@ -193,7 +195,7 @@ Together, these components form a powerful and flexible virtualization stack, wi

Example 1:
- CPU cores share the same singular L3 cache, so this cannot be optimised.
- CPU cores utilise different L1 and L2 caches, so isolatng corresponding thread pairs will help improve performance.
- CPU cores utilise different L1 and L2 caches, so isolating corresponding thread pairs will help improve performance.
- Thus, if limiting the virtual machine to a maximum of 4 threads, there are 10 possible optimal configurations:
- T<sub>0</sub>+T<sub>4</sub>
- T<sub>1</sub>+T<sub>5</sub>
Expand Down
6 changes: 3 additions & 3 deletions install/ExtractPrograms.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Function GetApplicationIcon {
# Args:
# - 'Names': An array of application names.
# - 'Paths': An array of executable paths.
# - 'Source': The source of the applications (e.g. Windows Registry, Package manangers, Universal Windows Platform (UWP), etc.)
# - 'Source': The source of the applications (e.g. Windows Registry, Package managers, Universal Windows Platform (UWP), etc.)
function PrintArrayData {
param (
[string[]]$Names,
Expand Down Expand Up @@ -240,7 +240,7 @@ function AppSearchUWP {
PrintArrayData -Names $exeNames -Paths $exePaths -Source "uwp"
}

# Name: 'AppSearchWinReg'
# Name: 'AppSearchChocolatey'
# Role: Search for chocolatey shims.
function AppSearchChocolatey {
# Initialise empty arrays.
Expand Down Expand Up @@ -272,7 +272,7 @@ function AppSearchChocolatey {
}
}

# Name: 'AppSearchWinReg'
# Name: 'AppSearchScoop'
# Role: Search for scoop shims.
function AppSearchScoop {
# Initialise empty arrays.
Expand Down
71 changes: 56 additions & 15 deletions oem/install.bat
Original file line number Diff line number Diff line change
@@ -1,25 +1,66 @@
@echo off
title WinApps Setup Wizard

reg import %~dp0\RDPApps.reg

if exists %~dp0\Container.reg (
reg import %~dp0\Container.reg
REM Check for administrative privileges
fltmc >nul 2>&1 || (
echo [INFO] Script not running as administrator. Attempting to relaunch with elevation...
powershell -Command "Start-Process '%~f0' -Verb runAs"
exit /b 0
)

REM Create network profile cleanup scheduled task
copy %~dp0\NetProfileCleanup.ps1 %windir%
set "taskname=NetworkProfileCleanup"
set "command=powershell.exe -ExecutionPolicy Bypass -File "%windir%\NetProfileCleanup.ps1^""
REM Confirm the user wants to proceed with setup
echo ============================================
echo WinApps Setup Wizard
echo ============================================
echo.
echo Press any key to continue or close this window to cancel...
pause >nul
echo.
echo [INFO] Starting setup...

schtasks /query /tn "%taskname%" >nul 2>&1
REM Apply RDP and system configuration tweaks
echo [INFO] Importing "RDPApps.reg"...
reg import "%~dp0RDPApps.reg" >nul 2>&1
if %ERRORLEVEL% equ 0 (
echo Task "%taskname%" already exists, deleting it first...
schtasks /delete /tn "%taskname%" /f
echo [SUCCESS] Imported "RDPApps.reg".
) else (
echo [ERROR] Failed to import "RDPApps.reg".
)

schtasks /create /tn "%taskname%" /tr "%command%" /sc onstart /ru "SYSTEM" /rl HIGHEST /f
if %ERRORLEVEL% equ 0 (
echo Scheduled task "%taskname%" created successfully.
REM Configure the system clock to use UTC instead of local time
if exist "%~dp0Container.reg" (
echo [INFO] Importing "Container.reg"...
reg import "%~dp0Container.reg" >nul 2>&1
if %ERRORLEVEL% equ 0 (
echo [SUCCESS] Imported "Container.reg".
) else (
echo [ERROR] Failed to import "Container.reg".
)
) else (
echo Failed to create scheduled task.
echo [WARNING] "Container.reg" not found. Skipping...
)

REM Create a startup task to clean up stale network profiles
echo [INFO] Creating network profile cleanup task...

REM Initialise values required to create the startup task
set "scriptpath=%windir%\NetProfileCleanup.ps1"
set "taskname=WinApps_NetworkProfileCleanup"
set "command=powershell.exe -ExecutionPolicy Bypass -File ""%scriptpath%"""

REM Copy the script to the Windows directory
copy /Y "%~dp0NetProfileCleanup.ps1" "%scriptpath%" >nul
if %ERRORLEVEL% neq 0 (
echo [ERROR] Failed to copy "NetProfileCleanup.ps1" to "%windir%".
) else (
schtasks /create /tn "%taskname%" /tr "%command%" /sc onstart /ru "SYSTEM" /rl HIGHEST /f >nul 2>&1
if %ERRORLEVEL% equ 0 (
echo [SUCCESS] Created scheduled task "%taskname%".
) else (
echo [ERROR] Failed to create scheduled task "%taskname%".
)
)

echo.
echo Press any key to exit...
pause >nul
1 change: 0 additions & 1 deletion packages/winapps/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ stdenv.mkDerivation rec {
];

patches = [
./winapps.patch
./setup.patch
];

Expand Down
4 changes: 2 additions & 2 deletions packages/winapps/setup.patch
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ index 0debe4d..6aeea08 100755
readonly USER_BIN_PATH_WIN='\\tsclient\home\.local\bin' # WINDOWS path to 'bin' directory for a '--user' WinApps installation.
# 'SOURCE'
-readonly SYS_SOURCE_PATH="${SYS_BIN_PATH}/winapps-src" # UNIX path to WinApps source directory for a '--system' WinApps installation.
-readonly USER_SOURCE_PATH="${USER_BIN_PATH}/winapps-src" # UNIX path to WinApps source directory for a '--system' WinApps installation.
-readonly USER_SOURCE_PATH="${USER_BIN_PATH}/winapps-src" # UNIX path to WinApps source directory for a '--user' WinApps installation.
+readonly SYS_SOURCE_PATH="@out@/src" # UNIX path to WinApps source directory for a '--system' WinApps installation.
+readonly USER_SOURCE_PATH="@out@/src" # UNIX path to WinApps source directory for a '--system' WinApps installation.
+readonly USER_SOURCE_PATH="@out@/src" # UNIX path to WinApps source directory for a '--user' WinApps installation.
# 'APP'
readonly SYS_APP_PATH="/usr/share/applications" # UNIX path to 'applications' directory for a '--system' WinApps installation.
readonly USER_APP_PATH="${HOME}/.local/share/applications" # UNIX path to 'applications' directory for a '--user' WinApps installation.
Expand Down
11 changes: 0 additions & 11 deletions packages/winapps/winapps.patch

This file was deleted.

12 changes: 6 additions & 6 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ readonly EC_BAD_ARGUMENT="2" # Unsupported argument passed to script.
readonly EC_EXISTING_INSTALL="3" # Existing conflicting WinApps installation.
readonly EC_NO_CONFIG="4" # Absence of a valid WinApps configuration file.
readonly EC_MISSING_DEPS="5" # Missing dependencies.
readonly EC_NO_SUDO="6" # Insufficient privilages to invoke superuser access.
readonly EC_NO_SUDO="6" # Insufficient privileges to invoke superuser access.
readonly EC_NOT_IN_GROUP="7" # Current user not in group 'libvirt' and/or 'kvm'.
readonly EC_VM_OFF="8" # Windows 'libvirt' VM powered off.
readonly EC_VM_PAUSED="9" # Windows 'libvirt' VM paused.
Expand All @@ -40,7 +40,7 @@ readonly USER_BIN_PATH="${HOME}/.local/bin" # UNIX path to 'bin' dir
readonly USER_BIN_PATH_WIN='\\tsclient\home\.local\bin' # WINDOWS path to 'bin' directory for a '--user' WinApps installation.
# 'SOURCE'
readonly SYS_SOURCE_PATH="${SYS_BIN_PATH}/winapps-src" # UNIX path to WinApps source directory for a '--system' WinApps installation.
readonly USER_SOURCE_PATH="${USER_BIN_PATH}/winapps-src" # UNIX path to WinApps source directory for a '--system' WinApps installation.
readonly USER_SOURCE_PATH="${USER_BIN_PATH}/winapps-src" # UNIX path to WinApps source directory for a '--user' WinApps installation.
# 'APP'
readonly SYS_APP_PATH="/usr/share/applications" # UNIX path to 'applications' directory for a '--system' WinApps installation.
readonly USER_APP_PATH="${HOME}/.local/share/applications" # UNIX path to 'applications' directory for a '--user' WinApps installation.
Expand Down Expand Up @@ -151,7 +151,7 @@ function waGetSourceCode() {
SCRIPT_DIR_PATH=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")

# Check if winapps is currently installed on $SOURCE_PATH
if [[ -f "$SCRIPT_DIR_PATH/winapps" && "$SCRIPT_DIR_PATH" -ne "$SOURCE_PATH" ]]; then
if [[ -f "$SCRIPT_DIR_PATH/winapps" && "$SCRIPT_DIR_PATH" != "$SOURCE_PATH" ]]; then
# Display a warning.
echo -e "${WARNING_TEXT}[WARNING]${CLEAR_TEXT} You are running a WinApps installation located outside of default location '${SOURCE_PATH}'. A new installation will be created."
echo -e "${WARNING_TEXT}[WARNING]${CLEAR_TEXT} You might want to remove your old installation on '${SCRIPT_DIR_PATH}'."
Expand Down Expand Up @@ -1156,7 +1156,7 @@ function waFindInstalled() {
echo "IF EXIST \"${WIN_EXECUTABLE}\" ECHO ${APPLICATION} >> ${TMP_INST_FILE_PATH_WIN}" >>"$BATCH_SCRIPT_PATH"
done

# Append a command to the batch script to run the PowerShell script and store it's output in the 'detected' file.
# Append a command to the batch script to run the PowerShell script and store its output in the 'detected' file.
# shellcheck disable=SC2129 # Silence warning regarding repeated redirects.
echo "powershell.exe -ExecutionPolicy Bypass -File ${PS_SCRIPT_HOME_PATH_WIN} > ${DETECTED_FILE_PATH_WIN}" >>"$BATCH_SCRIPT_PATH"

Expand Down Expand Up @@ -1279,7 +1279,7 @@ function waConfigureApp() {

# Source 'Info' File Containing:
# - The Application Name (FULL_NAME)
# - The Shortcut Nsame (NAME)
# - The Shortcut Name (NAME)
# - Application Categories (CATEGORIES)
# - Executable Path (WIN_EXECUTABLE)
# - Supported MIME Types (MIME_TYPES)
Expand Down Expand Up @@ -1379,7 +1379,7 @@ function waConfigureApps() {
for OSA in "${OSA_LIST[@]}"; do
# Source 'Info' File Containing:
# - The Application Name (FULL_NAME)
# - The Shortcut Nsame (NAME)
# - The Shortcut Name (NAME)
# - Application Categories (CATEGORIES)
# - Executable Path (WIN_EXECUTABLE)
# - Supported MIME Types (MIME_TYPES)
Expand Down