; LedGrab NSIS Installer Script ; Cross-compilable on Linux: apt install nsis && makensis installer.nsi ; ; Expects the portable build to already exist at build/LedGrab/ ; (run build-dist-windows.sh first) !include "MUI2.nsh" !include "FileFunc.nsh" ; ── Metadata ──────────────────────────────────────────────── !define APPNAME "LedGrab" !define VBSNAME "start-hidden.vbs" !define DESCRIPTION "Ambient lighting system — captures screen content and drives LED strips in real time" !define VERSIONMAJOR 0 !define VERSIONMINOR 1 !define VERSIONBUILD 0 ; Set from command line: makensis -DVERSION=0.1.0 installer.nsi !ifndef VERSION !define VERSION "${VERSIONMAJOR}.${VERSIONMINOR}.${VERSIONBUILD}" !endif Name "${APPNAME} v${VERSION}" OutFile "build\${APPNAME}-v${VERSION}-win-x64-setup.exe" InstallDir "$LOCALAPPDATA\${APPNAME}" InstallDirRegKey HKCU "Software\${APPNAME}" "InstallDir" RequestExecutionLevel user SetCompressor /SOLID lzma ; ── Modern UI Configuration ───────────────────────────────── !define MUI_ABORTWARNING ; ── Pages ─────────────────────────────────────────────────── ; Use MUI_FINISHPAGE_RUN_FUNCTION instead of MUI_FINISHPAGE_RUN_PARAMETERS — ; NSIS Exec command chokes on the quoting with RUN_PARAMETERS. !define MUI_FINISHPAGE_RUN "" !define MUI_FINISHPAGE_RUN_TEXT "Launch ${APPNAME}" !define MUI_FINISHPAGE_RUN_FUNCTION LaunchApp !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES !insertmacro MUI_LANGUAGE "English" ; ── Functions ───────────────────────────────────────────── Function LaunchApp ExecShell "open" "wscript.exe" '"$INSTDIR\scripts\${VBSNAME}"' Sleep 2000 ExecShell "open" "http://localhost:8080/" FunctionEnd ; Detect running instance before install (file lock check on python.exe) Function .onInit IfFileExists "$INSTDIR\python\python.exe" 0 done ClearErrors FileOpen $0 "$INSTDIR\python\python.exe" a IfErrors locked FileClose $0 Goto done locked: MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION \ "${APPNAME} is currently running.$\n$\nYes = Stop and continue$\nNo = Continue anyway (may cause errors)$\nCancel = Abort" \ IDYES kill IDNO done Abort kill: nsExec::ExecToLog 'wmic process where "ExecutablePath like $\'%${APPNAME}%python%$\'" call terminate' Sleep 2000 done: FunctionEnd ; ── Installer Sections ────────────────────────────────────── Section "!${APPNAME} (required)" SecCore SectionIn RO SetOutPath "$INSTDIR" ; Copy the entire portable build File /r "build\LedGrab\python" File /r "build\LedGrab\app" File /r "build\LedGrab\scripts" File "build\LedGrab\LedGrab.bat" ; Create data and logs directories CreateDirectory "$INSTDIR\data" CreateDirectory "$INSTDIR\logs" ; Create uninstaller WriteUninstaller "$INSTDIR\uninstall.exe" ; Start Menu shortcuts CreateDirectory "$SMPROGRAMS\${APPNAME}" CreateShortcut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" \ "wscript.exe" '"$INSTDIR\scripts\${VBSNAME}"' \ "$INSTDIR\python\pythonw.exe" 0 CreateShortcut "$SMPROGRAMS\${APPNAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe" ; Registry: install location + Add/Remove Programs entry WriteRegStr HKCU "Software\${APPNAME}" "InstallDir" "$INSTDIR" WriteRegStr HKCU "Software\${APPNAME}" "Version" "${VERSION}" WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" \ "DisplayName" "${APPNAME}" WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" \ "DisplayVersion" "${VERSION}" WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" \ "UninstallString" '"$INSTDIR\uninstall.exe"' WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" \ "InstallLocation" "$INSTDIR" WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" \ "Publisher" "Alexei Dolgolyov" WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" \ "URLInfoAbout" "https://git.dolgolyov-family.by/alexei.dolgolyov/wled-screen-controller-mixed" WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" \ "NoModify" 1 WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" \ "NoRepair" 1 ; Calculate installed size for Add/Remove Programs ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 IntFmt $0 "0x%08X" $0 WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" \ "EstimatedSize" "$0" SectionEnd Section "Desktop shortcut" SecDesktop CreateShortcut "$DESKTOP\${APPNAME}.lnk" \ "wscript.exe" '"$INSTDIR\scripts\${VBSNAME}"' \ "$INSTDIR\python\pythonw.exe" 0 SectionEnd Section "Start with Windows" SecAutostart CreateShortcut "$SMSTARTUP\${APPNAME}.lnk" \ "wscript.exe" '"$INSTDIR\scripts\${VBSNAME}"' \ "$INSTDIR\python\pythonw.exe" 0 SectionEnd ; ── Section Descriptions ──────────────────────────────────── !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${SecCore} \ "Install ${APPNAME} server and all required files." !insertmacro MUI_DESCRIPTION_TEXT ${SecDesktop} \ "Create a shortcut on your desktop." !insertmacro MUI_DESCRIPTION_TEXT ${SecAutostart} \ "Start ${APPNAME} automatically when you log in." !insertmacro MUI_FUNCTION_DESCRIPTION_END ; ── Uninstaller ───────────────────────────────────────────── Section "Uninstall" ; Remove shortcuts Delete "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" Delete "$SMPROGRAMS\${APPNAME}\Uninstall.lnk" RMDir "$SMPROGRAMS\${APPNAME}" Delete "$DESKTOP\${APPNAME}.lnk" Delete "$SMSTARTUP\${APPNAME}.lnk" ; Remove application files (but NOT data/ — preserve user config) RMDir /r "$INSTDIR\python" RMDir /r "$INSTDIR\app" RMDir /r "$INSTDIR\scripts" Delete "$INSTDIR\LedGrab.bat" Delete "$INSTDIR\uninstall.exe" ; Remove logs (but keep data/) RMDir /r "$INSTDIR\logs" ; Try to remove install dir (only succeeds if empty — data/ may remain) RMDir "$INSTDIR" ; Remove registry keys DeleteRegKey HKCU "Software\${APPNAME}" DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" SectionEnd