Files
2026-06-01 19:34:25 -07:00

232 lines
6.6 KiB
NSIS

; codewhale.nsi — NSIS installer for CodeWhale (Windows)
;
; Requirements (see https://github.com/Hmbown/CodeWhale/issues/1983):
; - Install codewhale.exe and codewhale-tui.exe side-by-side
; - Default to %LOCALAPPDATA%\Programs\CodeWhale\bin
; - Add install dir to current-user PATH
; - Uninstaller removes the PATH entry
;
; Usage:
; 1. Place both .exe files next to this script:
; codewhale.exe
; codewhale-tui.exe
; 2. Build:
; makensis /DVERSION=1.2.3 codewhale.nsi
; 3. Output: CodeWhaleSetup.exe (in current directory)
;--------------------------------
; Includes
;--------------------------------
!include "MUI2.nsh"
!include "FileFunc.nsh"
!include "StrFunc.nsh"
${StrStr}
${UnStrStr}
;--------------------------------
; General
;--------------------------------
!ifndef VERSION
!define VERSION "0.0.0"
!endif
!define PRODUCT_NAME "CodeWhale"
!define PRODUCT_PUBLISHER "Hmbown"
!define PRODUCT_WEB_SITE "https://github.com/Hmbown/CodeWhale"
Name "${PRODUCT_NAME} ${VERSION}"
OutFile "CodeWhaleSetup.exe"
InstallDir "$LOCALAPPDATA\Programs\CodeWhale"
RequestExecutionLevel user
BrandingText "${PRODUCT_NAME} Installer"
;--------------------------------
; Interface Settings
;--------------------------------
!define MUI_ABORTWARNING
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
;--------------------------------
; Pages
;--------------------------------
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "..\..\LICENSE"
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
;--------------------------------
; Languages
;--------------------------------
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "SimpChinese"
;--------------------------------
; Installer Sections
;--------------------------------
Section "Install" SecInstall
SetOutPath "$INSTDIR\bin"
; Copy binaries
File "codewhale.exe"
File "codewhale-tui.exe"
; Write uninstaller
WriteUninstaller "$INSTDIR\Uninstall.exe"
; Add to current-user PATH
; Read existing PATH, append only when the exact entry is absent.
ReadRegStr $0 HKCU "Environment" "Path"
StrCpy $2 ";$0;"
StrCpy $3 ";$INSTDIR\bin;"
${StrStr} $1 $2 $3
StrCmp $1 "" 0 path_already_set
StrCmp $0 "" empty_path
WriteRegExpandStr HKCU "Environment" "Path" "$0;$INSTDIR\bin"
Goto path_done
empty_path:
WriteRegExpandStr HKCU "Environment" "Path" "$INSTDIR\bin"
path_done:
; Notify the system about the environment change
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
path_already_set:
; Store install directory for uninstaller
WriteRegStr HKCU "Software\${PRODUCT_NAME}" "InstallDir" "$INSTDIR"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayName" "${PRODUCT_NAME}"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\""
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "QuietUninstallString" "$\"$INSTDIR\Uninstall.exe$\" /S"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "Publisher" "${PRODUCT_PUBLISHER}"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayVersion" "${VERSION}"
WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoModify" 1
WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoRepair" 1
; Calculate and store installed size
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
IntFmt $0 "0x%08X" $0
WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "EstimatedSize" "$0"
SectionEnd
;--------------------------------
; Uninstaller Section
;--------------------------------
Section "Uninstall"
; Remove binaries
Delete "$INSTDIR\bin\codewhale.exe"
Delete "$INSTDIR\bin\codewhale-tui.exe"
Delete "$INSTDIR\Uninstall.exe"
RMDir "$INSTDIR\bin"
RMDir "$INSTDIR"
; Remove from current-user PATH
ReadRegStr $0 HKCU "Environment" "Path"
StrCpy $2 ";$0;"
StrCpy $3 ";$INSTDIR\bin;"
${UnStrStr} $1 $2 $3
StrCmp $1 "" path_clean_done
Push "$0"
Push "$INSTDIR\bin"
Call un.RemoveFromPath
Pop $0
WriteRegExpandStr HKCU "Environment" "Path" "$0"
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
path_clean_done:
; Remove registry keys
DeleteRegKey HKCU "Software\${PRODUCT_NAME}"
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
SectionEnd
;--------------------------------
; Helper: Remove exact directory entries from PATH (uninstaller version)
; Input: PATH string (on stack), directory to remove (on stack)
; Output: cleaned PATH (on stack)
;--------------------------------
Function un.RemoveFromPath
Exch $R0 ; directory to remove
Exch
Exch $R1 ; original PATH
Push $R2 ; padded path
Push $R3 ; padded needle
Push $R4 ; match result
Push $R5 ; prefix
Push $R6 ; suffix
Push $R7 ; offset/length
loop:
StrCmp $R1 "" done
StrCpy $R2 ";$R1;"
StrCpy $R3 ";$R0;"
${UnStrStr} $R4 $R2 $R3
StrCmp $R4 "" done
; Prefix before the exact `;dir;` match in the padded PATH.
StrLen $R5 $R2
StrLen $R6 $R4
IntOp $R6 $R5 - $R6
StrCpy $R5 $R2 $R6
; Suffix after the exact `;dir;` match in the padded PATH.
StrLen $R7 $R3
IntOp $R7 $R6 + $R7
StrCpy $R6 $R2 "" $R7
Push $R5
Call un.TrimPathEdgeSemicolons
Pop $R5
Push $R6
Call un.TrimPathEdgeSemicolons
Pop $R6
StrCmp $R5 "" 0 +3
StrCpy $R1 $R6
Goto loop
StrCmp $R6 "" 0 +3
StrCpy $R1 $R5
Goto loop
StrCpy $R1 "$R5;$R6"
Goto loop
done:
Pop $R7
Pop $R6
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R0
Exch $R1
FunctionEnd
Function un.TrimPathEdgeSemicolons
Exch $R9
Push $R8
trim_leading:
StrCpy $R8 $R9 1
StrCmp $R8 ";" 0 trim_trailing
StrCpy $R9 $R9 "" 1
Goto trim_leading
trim_trailing:
StrLen $R8 $R9
IntCmp $R8 0 trim_done
IntOp $R8 $R8 - 1
StrCpy $R8 $R9 1 $R8
StrCmp $R8 ";" 0 trim_done
StrLen $R8 $R9
IntOp $R8 $R8 - 1
StrCpy $R9 $R9 $R8
Goto trim_trailing
trim_done:
Pop $R8
Exch $R9
FunctionEnd