feat!(nsis): add an option to customize start menu folder (#9994)

This commit is contained in:
Tony 2024-06-26 14:17:02 +08:00 committed by GitHub
parent a15a97594f
commit f21029b1bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 155 additions and 18 deletions

View File

@ -0,0 +1,5 @@
---
"tauri-bundler": "patch:breaking"
---
Changed NSIS start menu shortcut to be placed directly inside `%AppData%\Microsoft\Windows\Start Menu\Programs` without an additional folder. You can get the old behavior by setting `bundle > nsis > startMenuFolder` to the same value as your `productName`

View File

@ -0,0 +1,6 @@
---
"tauri-utils": "patch:feat"
"tauri-bundler": "patch:feat"
---
Add `bundle > nsis > startMenuFolder` option to customize start menu folder for NSIS installer

View File

@ -2306,6 +2306,13 @@
}
]
},
"startMenuFolder": {
"description": "Set the folder name for the start menu shortcut.\n\n Use this option if you have multiple apps and wish to group their shortcuts under one folder\n or if you generally prefer to set your shortcut inside a folder.\n\n Examples:\n - `AwesomePublisher`, shortcut will be placed in `%AppData%\\Microsoft\\Windows\\Start Menu\\Programs\\AwesomePublisher\\<your-app>.lnk`\n - If unset, shortcut will be placed in `%AppData%\\Microsoft\\Windows\\Start Menu\\Programs\\<your-app>.lnk`",
"type": [
"string",
"null"
]
},
"installerHooks": {
"description": "A path to a `.nsh` file that contains special NSIS macros to be hooked into the\n main installer.nsi script.\n\n Supported hooks are:\n - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.\n - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.\n - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.\n - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.\n\n\n ### Example\n\n ```nsh\n !define NSIS_HOOK_PREINSTALL \"NSIS_HOOK_PREINSTALL_\"\n !macro NSIS_HOOK_PREINSTALL_\n MessageBox MB_OK \"PreInstall\"\n !macroend\n\n !define NSIS_HOOK_POSTINSTALL \"NSIS_HOOK_POSTINSTALL_\"\n !macro NSIS_HOOK_POSTINSTALL_\n MessageBox MB_OK \"PostInstall\"\n !macroend\n\n !define NSIS_HOOK_PREUNINSTALL \"NSIS_HOOK_PREUNINSTALL_\"\n !macro NSIS_HOOK_PREUNINSTALL_\n MessageBox MB_OK \"PreUnInstall\"\n !macroend\n\n !define NSIS_HOOK_POSTUNINSTALL \"NSIS_HOOK_POSTUNINSTALL_\"\n !macro NSIS_HOOK_POSTUNINSTALL_\n MessageBox MB_OK \"PostUninstall\"\n !macroend\n\n ```",
"type": [

View File

@ -776,6 +776,16 @@ pub struct NsisConfig {
/// See <https://nsis.sourceforge.io/Reference/SetCompressor>
#[serde(default)]
pub compression: NsisCompression,
/// Set the folder name for the start menu shortcut.
///
/// Use this option if you have multiple apps and wish to group their shortcuts under one folder
/// or if you generally prefer to set your shortcut inside a folder.
///
/// Examples:
/// - `AwesomePublisher`, shortcut will be placed in `%AppData%\Microsoft\Windows\Start Menu\Programs\AwesomePublisher\<your-app>.lnk`
/// - If unset, shortcut will be placed in `%AppData%\Microsoft\Windows\Start Menu\Programs\<your-app>.lnk`
#[serde(alias = "start-menu-folder")]
pub start_menu_folder: Option<String>,
/// A path to a `.nsh` file that contains special NSIS macros to be hooked into the
/// main installer.nsi script.
///

View File

@ -417,6 +417,15 @@ pub struct NsisSettings {
pub display_language_selector: bool,
/// Set compression algorithm used to compress files in the installer.
pub compression: NsisCompression,
/// Set the folder name for the start menu shortcut.
///
/// Use this option if you have multiple apps and wish to group their shortcuts under one folder
/// or if you generally prefer to set your shortcut inside a folder.
///
/// Examples:
/// - `AwesomePublisher`, shortcut will be placed in `%AppData%\Microsoft\Windows\Start Menu\Programs\AwesomePublisher\<your-app>.lnk`
/// - If unset, shortcut will be placed in `%AppData%\Microsoft\Windows\Start Menu\Programs\<your-app>.lnk`
pub start_menu_folder: Option<String>,
/// A path to a `.nsh` file that contains special NSIS macros to be hooked into the
/// main installer.nsi script.
///
@ -831,9 +840,7 @@ impl Settings {
/// Returns the path to the specified binary.
pub fn binary_path(&self, binary: &BundleBinary) -> PathBuf {
let mut path = self.project_out_directory.clone();
path.push(binary.name());
path
self.project_out_directory.join(binary.name())
}
/// Returns the list of binaries to bundle.

View File

@ -253,6 +253,10 @@ fn build_nsis_app_installer(
let installer_hooks = dunce::canonicalize(installer_hooks)?;
data.insert("installer_hooks", to_json(installer_hooks));
}
if let Some(start_menu_folder) = &nsis.start_menu_folder {
data.insert("start_menu_folder", to_json(start_menu_folder));
}
}
let compression = settings
@ -330,7 +334,12 @@ fn build_nsis_app_installer(
let main_binary_path = settings.binary_path(main_binary).with_extension("exe");
data.insert(
"main_binary_name",
to_json(main_binary.name().replace(".exe", "")),
to_json(
main_binary_path
.file_stem()
.and_then(|file_name| file_name.to_str())
.unwrap_or_else(|| main_binary.name()),
),
);
data.insert("main_binary_path", to_json(&main_binary_path));

View File

@ -9,7 +9,7 @@ ManifestDPIAwareness PerMonitorV2
!if "{{compression}}" == "none"
SetCompress off
!else
; Set the compression algorithm. Default is LZMA.
; Set the compression algorithm. We default to LZMA.
SetCompressor /SOLID "{{compression}}"
!endif
@ -57,6 +57,7 @@ ${StrLoc}
!define MANUPRODUCTKEY "Software\${MANUFACTURER}\${PRODUCTNAME}"
!define UNINSTALLERSIGNCOMMAND "{{uninstaller_sign_cmd}}"
!define ESTIMATEDSIZE "{{estimated_size}}"
!define STARTMENUFOLDER "{{start_menu_folder}}"
Var PassiveMode
Var UpdateMode
@ -337,7 +338,12 @@ FunctionEnd
; 6. Start menu shortcut page
Var AppStartMenuFolder
!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
!if "${STARTMENUFOLDER}" != ""
!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "${STARTMENUFOLDER}"
!else
!define MUI_PAGE_CUSTOMFUNCTION_PRE Skip
!endif
!insertmacro MUI_PAGE_STARTMENU Application $AppStartMenuFolder
; 7. Installation page
@ -722,13 +728,27 @@ Section Uninstall
; Remove start menu shortcut
!insertmacro MUI_STARTMENU_GETFOLDER Application $AppStartMenuFolder
!insertmacro UnpinShortcut "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk"
Delete "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk"
RMDir "$SMPROGRAMS\$AppStartMenuFolder"
!insertmacro IsShortcutTarget "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
Pop $0
${If} $0 = 1
!insertmacro UnpinShortcut "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk"
Delete "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk"
RMDir "$SMPROGRAMS\$AppStartMenuFolder"
${EndIf}
!insertmacro IsShortcutTarget "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
Pop $0
${If} $0 = 1
!insertmacro UnpinShortcut "$SMPROGRAMS\${PRODUCTNAME}.lnk"
Delete "$SMPROGRAMS\${PRODUCTNAME}.lnk"
${EndIf}
; Remove desktop shortcuts
!insertmacro UnpinShortcut "$DESKTOP\${PRODUCTNAME}.lnk"
Delete "$DESKTOP\${PRODUCTNAME}.lnk"
!insertmacro IsShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
Pop $0
${If} $0 = 1
!insertmacro UnpinShortcut "$DESKTOP\${PRODUCTNAME}.lnk"
Delete "$DESKTOP\${PRODUCTNAME}.lnk"
${EndIf}
${EndIf}
; Remove registry information for add/remove programs
@ -767,6 +787,10 @@ Function RestorePreviousInstallLocation
StrCpy $INSTDIR $4
FunctionEnd
Function Skip
Abort
FunctionEnd
Function SkipIfPassive
${IfThen} $PassiveMode = 1 ${|} Abort ${|}
FunctionEnd
@ -774,8 +798,23 @@ FunctionEnd
Function CreateOrUpdateStartMenuShortcut
; We used to use product name as MAINBINARYNAME
; migrate old shortcuts to target the new MAINBINARYNAME
${If} ${FileExists} "$DESKTOP\${PRODUCTNAME}.lnk"
!insertmacro SetShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
StrCpy $R0 0
!insertmacro IsShortcutTarget "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCTNAME}.exe"
Pop $0
${If} $0 = 1
!insertmacro SetShortcutTarget "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
StrCpy $R0 1
${EndIf}
!insertmacro IsShortcutTarget "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCTNAME}.exe"
Pop $0
${If} $0 = 1
!insertmacro SetShortcutTarget "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
StrCpy $R0 1
${EndIf}
${If} $R0 = 1
Return
${EndIf}
@ -785,16 +824,23 @@ Function CreateOrUpdateStartMenuShortcut
Return
${EndIf}
CreateDirectory "$SMPROGRAMS\$AppStartMenuFolder"
CreateShortcut "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
!insertmacro SetLnkAppUserModelId "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk"
!if "${STARTMENUFOLDER}" != ""
CreateDirectory "$SMPROGRAMS\$AppStartMenuFolder"
CreateShortcut "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
!insertmacro SetLnkAppUserModelId "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk"
!else
CreateShortcut "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
!insertmacro SetLnkAppUserModelId "$SMPROGRAMS\${PRODUCTNAME}.lnk"
!endif
FunctionEnd
Function CreateOrUpdateDesktopShortcut
; We used to use product name as MAINBINARYNAME
; migrate old shortcuts to target the new MAINBINARYNAME
${If} ${FileExists} "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk"
!insertmacro SetShortcutTarget "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
!insertmacro IsShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCTNAME}.exe"
Pop $0
${If} $0 = 1
!insertmacro SetShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
Return
${EndIf}

View File

@ -131,3 +131,42 @@
${IUnknown::Release} $0 ""
${EndIf}
!macroend
!define /ifndef MAX_PATH 260
!define /ifndef SLGP_RAWPATH 0x4
; Test if a .lnk shortcut's target is target,
; use Pop to get the result, 1 is yes, 0 is no,
; note that this macro modifies $0, $1, $2, $3
;
; Exmaple usage:
; !insertmacro "IsShortCutTarget" "C:\Users\Public\Desktop\App.lnk" "C:\Program Files\App\App.exe"
; Pop $0
; ${If} $0 = 1
; MessageBox MB_OK "shortcut target matches"
; ${EndIf}
!macro IsShortcutTarget shortcut target
; $0: IShellLink
; $1: IPersistFile
; $2: Target path
; $3: Return value
StrCpy $3 0
!insertmacro ComHlpr_CreateInProcInstance ${CLSID_ShellLink} ${IID_IShellLink} r0 ""
${If} $0 P<> 0
${IUnknown::QueryInterface} $0 '("${IID_IPersistFile}", .r1)'
${If} $1 P<> 0
${IPersistFile::Load} $1 '("${shortcut}", ${STGM_READ})'
System::Alloc MAX_PATH
Pop $2
${IShellLink::GetPath} $0 '(.r2, ${MAX_PATH}, 0, ${SLGP_RAWPATH})'
${If} $2 == "${target}"
StrCpy $3 1
${EndIf}
System::Free $2
${IUnknown::Release} $1 ""
${EndIf}
${IUnknown::Release} $0 ""
${EndIf}
Push $3
!macroend

View File

@ -2306,6 +2306,13 @@
}
]
},
"startMenuFolder": {
"description": "Set the folder name for the start menu shortcut.\n\n Use this option if you have multiple apps and wish to group their shortcuts under one folder\n or if you generally prefer to set your shortcut inside a folder.\n\n Examples:\n - `AwesomePublisher`, shortcut will be placed in `%AppData%\\Microsoft\\Windows\\Start Menu\\Programs\\AwesomePublisher\\<your-app>.lnk`\n - If unset, shortcut will be placed in `%AppData%\\Microsoft\\Windows\\Start Menu\\Programs\\<your-app>.lnk`",
"type": [
"string",
"null"
]
},
"installerHooks": {
"description": "A path to a `.nsh` file that contains special NSIS macros to be hooked into the\n main installer.nsi script.\n\n Supported hooks are:\n - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.\n - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.\n - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.\n - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.\n\n\n ### Example\n\n ```nsh\n !define NSIS_HOOK_PREINSTALL \"NSIS_HOOK_PREINSTALL_\"\n !macro NSIS_HOOK_PREINSTALL_\n MessageBox MB_OK \"PreInstall\"\n !macroend\n\n !define NSIS_HOOK_POSTINSTALL \"NSIS_HOOK_POSTINSTALL_\"\n !macro NSIS_HOOK_POSTINSTALL_\n MessageBox MB_OK \"PostInstall\"\n !macroend\n\n !define NSIS_HOOK_PREUNINSTALL \"NSIS_HOOK_PREUNINSTALL_\"\n !macro NSIS_HOOK_PREUNINSTALL_\n MessageBox MB_OK \"PreUnInstall\"\n !macroend\n\n !define NSIS_HOOK_POSTUNINSTALL \"NSIS_HOOK_POSTUNINSTALL_\"\n !macro NSIS_HOOK_POSTUNINSTALL_\n MessageBox MB_OK \"PostUninstall\"\n !macroend\n\n ```",
"type": [

View File

@ -105,6 +105,7 @@ pub fn nsis_settings(config: NsisConfig) -> tauri_bundler::NsisSettings {
custom_language_files: config.custom_language_files,
display_language_selector: config.display_language_selector,
compression: config.compression,
start_menu_folder: config.start_menu_folder,
installer_hooks: config.installer_hooks,
}
}