!include "config.nsh" !include "EnvVarUpdate.nsh" # libraries used !include nsDialogs.nsh !include LogicLib.nsh # nsis config Name "${ProductName}" OutFile "${ExecutableName}" !define TemporaryFilesDir "$PLUGINSDIR\files" # used for files only needed by the installer itself, like the 3rd party installers SetCompressor "lzma" # codec to compress all delivered files RequestExecutionLevel "admin" # execution level the installer requests, user or admin # user vars # mainly used for uninstallation Var PackagesDir # anuga install root ($python\site-packages\anuga) Var ViewerInst # has viewer been installed Var ViewerDir # anuga viewer install root ($programfiles\anuga viewer) Var PythonInst # has python been installed Var PythonDir # python install root (C:\python) Var MinGWInst # has mingw been installed Var MinGWDir # mingw install root ($programfiles\mingw) Var NetCDFDir # netcdf binaries ($commonfiles\netcdf) Var ScientificPythonInst #has ScientificPython been installed Var NumpyInst #has Numpy been installed Var MatplotlibInst #has matplotlib beeen installed # support variables for user dialogs Var Dialog Var Control0 Var Control1 Var Control2 Var Control3 Var Control4 # UI config !define MUI_ICON "${InstallerIcon}" # installers icon # settings for the dialog header image !define MUI_HEADERIMAGE !define MUI_HEADERIMAGE_BITMAP "${HeaderBitmap}" !define MUI_HEADERIMAGE_RIGHT # bitmap on the welcome and finish page !define MUI_WELCOMEFINISHPAGE_BITMAP "${WelcomeFinishBitmap}" # the modern ui library !include MUI2.nsh # installer pages !insertmacro MUI_PAGE_WELCOME # welcome and introduction page Page custom EnterPython # install python and select directory Page custom EnterExtensions LeaveExtensions # install extensions Page custom EnterMinGW # install mingw and select directory !define MUI_LICENSEPAGE_TEXT_TOP "$(LicenseScrollText)" !insertmacro MUI_PAGE_LICENSE "$(LicenseFile)" # license page !insertmacro MUI_PAGE_COMPONENTS # select other install options !insertmacro MUI_PAGE_INSTFILES # compile/test/install anuga and viewer !define MUI_FINISHPAGE_LINK "$(WebsiteLabel)" !define MUI_FINISHPAGE_LINK_LOCATION "${Website}" !define MUI_FINISHPAGE_NOREBOOTSUPPORT !insertmacro MUI_PAGE_FINISH # end of installation ## uninstaller pages !insertmacro MUI_UNPAGE_COMPONENTS # select what to uninstall !insertmacro MUI_UNPAGE_CONFIRM # confirm uninstallation !insertmacro MUI_UNPAGE_INSTFILES # do it ## supported languages (string tables) !include "translation.nsh" # installer Section "$(section_mvcrp)" sec_mvcrp #SectionIn RO # read only, it's required SetOutPath "${TemporaryFilesDir}" File "${FileSource}\prereqs\${MVCRPInst}" ExecWait "${TemporaryFilesDir}\${MVCRPInst} /Q" SectionEnd Section "$(section_netcdf)" sec_ncdf #SectionIn RO # read only, it's required # install netcdf to default, no custom selection here StrCpy $NetCDFDir "${NetCDFDefaultFolder}" SetOutPath $NetCDFDir File /r "${FileSource}\prereqs\${NetCDFFolder}\*.*" # file extraction SectionEnd SectionGroup /e "!$(section_anuga_viewer)" sec_viewer Section # install anuga viewer StrCpy $ViewerDir "${AnugaViewerDefaultFolder}" SetOutPath $ViewerDir File /r "${FileSource}\${AnugaViewerFolder}\*.*" StrCpy $ViewerInst "1" SectionEnd Section "$(section_anuga_viewer_extension)" sec_ext # register file extension with anuga viewer WriteRegStr HKCR "${ViewerExtension}" "" "${ViewerExtensionAlias}" WriteRegStr HKCR "${ViewerExtensionAlias}\shell\open\command" "" "$ViewerDir\animate.exe %1" SectionEnd SectionGroupEnd Section "!$(section_anuga_install)" sec_install # anuga main SectionIn RO # update path environment ${EnvVarUpdate} $0 "PATH" "A" "HKLM" "$PythonDir" ${EnvVarUpdate} $0 "PATH" "A" "HKLM" "$MinGWDir\bin" ${EnvVarUpdate} $0 "PATH" "A" "HKLM" "$NetCDFDir" #ReadRegStr $0 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" #StrCpy $0 "$0;$PythonDir;$MinGWDir\bin;$NetCDFDir;" #WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $0 SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 StrCpy $PackagesDir "$PythonDir\Lib\site-packages" # delete old files SetOutPath "$PackagesDir" RMDir /r "$PackagesDir\anuga" RMDir /r "$PackagesDir\anuga_core" RMDir /r "$PackagesDir\anuga_validation" # copy anuga files File /r "${FileSource}\${AnugaFolder}\anuga" File /r "${FileSource}\${AnugaFolder}\anuga_core" File /r "${FileSource}\${AnugaFolder}\anuga_validation" #Set environment path only for the installer to access gcc and python ReadEnvStr $R0 "PATH" StrCpy $R0 "$R0;$MinGWDir\bin;$PythonDir\DLLs;$PythonDir" System::Call 'Kernel32::SetEnvironmentVariableA(t, t) i("PATH", R0).r2' ReadEnvStr $R0 "PATH" # compile anuga SetOutPath "$PackagesDir\anuga" ExecWait '"$PythonDir\python.exe" "$OUTDIR\compile_all.py"' SectionEnd Section "$(section_anuga_test)" sec_test # test anuga SetOutPath "$PackagesDir\anuga" ExecWait '"$PythonDir\python.exe" "$OUTDIR\test_all.py"' SectionEnd Section "$(section_anuga_validate)" sec_validate # validate anuga SetOutPath "$PackagesDir\anuga_validation\automated_validation_tests" Exec '"$PythonDir\python.exe" "$OUTDIR\validate_all.py"' SectionEnd !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${sec_mvcrp} $(description_mvcrp) !insertmacro MUI_DESCRIPTION_TEXT ${sec_ncdf} $(description_netcdf) !insertmacro MUI_DESCRIPTION_TEXT ${sec_install} $(description_anuga_install) !insertmacro MUI_DESCRIPTION_TEXT ${sec_test} $(description_anuga_test) !insertmacro MUI_DESCRIPTION_TEXT ${sec_validate} $(description_anuga_validate) !insertmacro MUI_DESCRIPTION_TEXT ${sec_viewer} $(description_anuga_viewer) !insertmacro MUI_DESCRIPTION_TEXT ${sec_ext} $(description_anuga_viewer_extension) !insertmacro MUI_FUNCTION_DESCRIPTION_END # function executed on initialization of the installer Function .onInit # prevent the installer from beeing executed twice a time System::Call "kernel32::CreateMutexA(i 0, i 0, t '$(^Name)') i .n ?e" # create a mutex Pop $0 StrCmp $0 0 0 find Return # launch normaly if mutex could be created = no other instance running find: StrLen $0 "$(^Name)" IntOp $0 $0 + 1 loop: FindWindow $1 '#32770' '' 0 $1 # search the installers window if another instance is already running IntCmp $1 0 +4 System::Call /NOUNLOAD "user32.dll::GetWindowText(i r1, t .r2, i r0) i.n" StrCmp $2 "$(^Name)" 0 loop # check back for correct window text System::Call "user32::SetForegroundWindow(i r1) i.n" # bring it to front if found Abort # then exit FunctionEnd Function .onGUIEnd RMDir /r "${TemporaryFilesDir}" FunctionEnd Function EnterPython # installbutton and directory selection !insertmacro MUI_HEADER_TEXT "$(page_python_title)" "$(page_python_subtitle)" nsDialogs::Create 1018 Pop $Dialog StrCmp $Dialog "error" 0 +2 Abort GetDlgItem $Control0 $HWNDPARENT 1 # get python directory ReadRegStr $PythonDir HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Python.exe" "" StrLen $0 $PythonDir IntOp $0 $0 - 10 StrCpy $PythonDir $PythonDir $0 # select default, if possible from registry IfFileExists "$PythonDir\python.exe" +2 StrCpy $PythonDir "C:\Python25" # create dialog items ${NSD_CreateLabel} 10 10 430 28 "$(page_python_install_label)" ${NSD_CreateButton} 40 50 370 24 "$(page_python_install_button)" Pop $Control1 ${NSD_CreateLabel} 10 100 430 28 "$(page_python_browse_label)" ${NSD_CreateDirRequest} 40 140 290 24 "$PythonDir" Pop $Control2 ${NSD_CreateButton} 340 140 70 24 "$(page_python_browse_button)" Pop $Control3 ${NSD_CreateLabel} 10 190 430 28 "$(page_python_outro)" # register dialog actions ${NSD_OnClick} $Control1 RunPythonSetup ${NSD_OnChange} $Control2 ValidatePythonDir ${NSD_OnClick} $Control3 BrowsePythonDir # check for valid python directory Call ValidatePythonDir # show the page nsDialogs::Show FunctionEnd # extract and run the python installer Function RunPythonSetup SetOutPath "${TemporaryFilesDir}" File "${FileSource}\prereqs\${PythonInst}" ExecShell "" '"${TemporaryFilesDir}\${PythonInst}"' StrCpy $PythonInst "1" EnableWindow $Control0 1 # enable next button FunctionEnd # browse for the python dir with a folder dialog Function BrowsePythonDir nsDialogs::SelectFolderDialog "$(page_python_browse_dialog_title)" $PythonDir Pop $0 StrCmp $0 "error" 0 +2 Return ${NSD_SetText} $Control2 $0 Call ValidatePythonDir FunctionEnd # enable next button if selected python dir is valid Function ValidatePythonDir ${NSD_GetText} $Control2 $PythonDir IfFileExists "$PythonDir\python.exe" ok EnableWindow $Control0 0 Return ok: EnableWindow $Control0 1 FunctionEnd Function EnterExtensions # installbuttons for missing extensions !insertmacro MUI_HEADER_TEXT "$(page_extensions_title)" "$(page_extensions_subtitle)" nsDialogs::Create 1018 Pop $Dialog StrCmp $Dialog "error" 0 +2 Abort GetDlgItem $Control0 $HWNDPARENT 1 ${NSD_CreateLabel} 10 10 430 28 "$(page_extensions_intro)" ${NSD_CreateLabel} 40 50 350 28 "$(page_extensions_numpy_ok)" Pop $Control1 ${NSD_CreateLabel} 40 100 350 28 "$(page_extensions_scientific_ok)" Pop $Control2 ${NSD_CreateLabel} 40 150 350 28 "$(page_extensions_matplotlib_ok)" Pop $Control3 ${NSD_CreateLabel} 10 190 430 28 "$(page_extensions_outro_next)" Pop $Control4 StrCpy $1 "0" StrCpy $2 "0" StrCpy $3 "0" StrCpy $4 "0" StrCpy $5 "0" IfFileExists "$PackagesDir\Numpy\*.py" 0 +2 IntOp $1 $1 + 1 IfFileExists "$PackagesDir\Scientific\*.py" 0 +2 IntOp $2 $2 + 1 IfFileExists "$PackagesDir\matplotlib\*.py" 0 +2 IntOp $3 $3 + 1 IntOp $4 $2 + $1 IntOp $5 $4 + $3 IntCmp $1 0 0 num_ok num_ok ${NSD_SetText} $Control1 "$(page_extensions_numpy_label_install)" num_ok: IntCmp $2 0 0 scien_ok scien_ok ${NSD_SetText} $Control2 "$(page_extensions_scientific_label_install)" scien_ok: IntCmp $3 0 0 matp_ok matp_ok ${NSD_SetText} $Control3 "$(page_extensions_matplotlib_label_install)" matp_ok: IntCmp $5 3 no_inst ${NSD_SetText} $Control4 "$(page_extensions_outro_install)" ${NSD_SetText} $Control0 "$(^InstallBtn)" no_inst: nsDialogs::Show FunctionEnd Function LeaveExtensions IntCmp $5 0 +2 Return SetOutPath "${TemporaryFilesDir}" IntCmp $1 1 after_num File "${FileSource}\prereqs\${NumpyInst}" ExecWait '"${TemporaryFilesDir}\${NumpyInst}"' StrCpy $NumpyInst "1" after_num: StrCmp $2 1 after_scien File "${FileSource}\prereqs\${ScientificInst}" ExecWait '"${TemporaryFilesDir}\${ScientificInst}"' StrCpy $ScientificPythonInst "1" after_scien: StrCmp $3 1 after_matp File "${FileSource}\prereqs\${MatplotlibInst}" ExecWait '"${TemporaryFilesDir}\${MatplotlibInst}"' StrCpy $MatplotlibInst "1" after_matp: FunctionEnd Function EnterMinGW # installbutton and directory selection !insertmacro MUI_HEADER_TEXT "$(page_mingw_title)" "$(page_mingw_subtitle)" nsDialogs::Create 1018 Pop $Dialog StrCmp $Dialog "error" 0 +2 Abort GetDlgItem $Control0 $HWNDPARENT 1 ReadRegStr $MinGWDir HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\MinGW" "InstallLocation" IfFileExists "$MinGWDir\bin\gcc.exe" +2 StrCpy $MinGWDir "C:\MinGW" ${NSD_CreateLabel} 10 10 430 28 "$(page_mingw_install_label)" ${NSD_CreateButton} 40 50 370 24 "$(page_mingw_install_button)" Pop $Control1 ${NSD_CreateLabel} 10 100 430 28 "$(page_mingw_browse_label)" ${NSD_CreateDirRequest} 40 140 290 24 "$MinGWDir" Pop $Control2 ${NSD_CreateButton} 340 140 70 24 "$(page_mingw_browse_button)" Pop $Control3 ${NSD_CreateLabel} 10 190 430 28 "$(page_mingw_outro)" ${NSD_OnClick} $Control1 RunMinGWSetup ${NSD_OnChange} $Control2 ValidateMinGWDir ${NSD_OnClick} $Control3 BrowseMinGWDir Call ValidateMinGWDir nsDialogs::Show FunctionEnd Function RunMinGWSetup SetOutPath "${TemporaryFilesDir}" File "${FileSource}\prereqs\${MinGWInst}" ExecWait '"${TemporaryFilesDir}\${MinGWInst}"' StrCpy $MinGWInst "1" Call ValidateMinGWDir FunctionEnd Function BrowseMinGWDir nsDialogs::SelectFolderDialog "$(page_mingw_browse_dialog_title)" $MinGWDir Pop $0 StrCmp $0 "error" 0 +2 Return ${NSD_SetText} $Control2 $0 Call ValidateMinGWDir FunctionEnd Function ValidateMinGWDir ${NSD_GetText} $Control2 $MinGWDir IfFileExists "$MinGWDir\bin\gcc.exe" ok EnableWindow $Control0 0 Return ok: EnableWindow $Control0 1 #Add the MingW\bin path to the envorinment variables #${EnvVarUpdate} $0 "PATH" "A" "HKCU" "$MinGWDir\bin" FunctionEnd Section -uninst_registry SectionIn RO SetOutPath "$PackagesDir\anuga" # write the uninstaller executable to disk WriteUninstaller "$OUTDIR\${UninstallerExecutableName}" # uninstall entry in System->Software, very detailed information :) WriteRegStr HKLM "${UninstallerRegistryKey}" "DisplayName" "${ProductName}" WriteRegStr HKLM "${UninstallerRegistryKey}" "DisplayVersion" "${ProductVersion}" WriteRegStr HKLM "${UninstallerRegistryKey}" "DisplayIcon" "$OUTDIR\${UninstallerExecutableName},0" WriteRegStr HKLM "${UninstallerRegistryKey}" "Publisher" "${Company}" WriteRegStr HKLM "${UninstallerRegistryKey}" "URLInfoAbout" "${Website}" WriteRegStr HKLM "${UninstallerRegistryKey}" "InstallLocation" "$INSTDIR" WriteRegStr HKLM "${UninstallerRegistryKey}" "InstallSource" "$EXEDIR" WriteRegStr HKLM "${UninstallerRegistryKey}" "UninstallString" "$OUTDIR\${UninstallerExecutableName}" WriteRegStr HKLM "${UninstallerRegistryKey}" "ModifyPath" "$OUTDIR\${UninstallerExecutableName}" WriteRegDWORD HKLM "SOFTWARE\${ProductName}" "AnugaViewerInstalled" $ViewerInst WriteRegStr HKLM "SOFTWARE\${ProductName}" "AnugaViewerDir" $ViewerDir WriteRegDWORD HKLM "SOFTWARE\${ProductName}" "PythonInstalled" $PythonInst WriteRegStr HKLM "SOFTWARE\${ProductName}" "PythonDir" $PythonDir WriteRegDWORD HKLM "SOFTWARE\${ProductName}" "ScientificPythonInstalled" $ScientificPythonInst WriteRegDWORD HKLM "SOFTWARE\${ProductName}" "NumpyInstalled" $NumpyInst WriteRegDWORD HKLM "SOFTWARE\${ProductName}" "MatplotlibInstalled" $MatplotlibInst WriteRegDWORD HKLM "SOFTWARE\${ProductName}" "MinGWInstalled" $MinGWInst WriteRegStr HKLM "SOFTWARE\${ProductName}" "MinGWDir" "$MinGWDir" WriteRegStr HKLM "SOFTWARE\${ProductName}" "NetCDFDir" "$NetCDFDir" SectionEnd # uninstaller Section "un.install" #Remove the MingW\bin path from the envorinment variables ReadRegStr $PythonDir HKEY_LOCAL_MACHINE "SOFTWARE\${ProductName}" "PythonDir" ${un.EnvVarUpdate} $0 "PATH" "R" "HKLM" "$PythonDir" ${un.EnvVarUpdate} $0 "PATH" "R" "HKLM" "$PythonDir\DLLs" ReadRegStr $NetCDFDir HKEY_LOCAL_MACHINE "SOFTWARE\${ProductName}" "NetCDFDir" ${un.EnvVarUpdate} $0 "PATH" "R" "HKLM" "$NetCDFDir" ReadRegStr $MinGWDir HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\MinGW" "InstallLocation" ${un.EnvVarUpdate} $0 "PATH" "R" "HKLM" "$MinGWDir\bin" ReadRegStr $INSTDIR HKLM "SOFTWARE\${ProductName}" "PythonDir" SetOutPath "$INSTDIR" RMDir /r "$INSTDIR\Lib\site-packages\anuga" RMDir /r "$INSTDIR\Lib\site-packages\anuga_core" RMDir /r "$INSTDIR\Lib\site-packages\anuga_validation" ReadRegDWORD $0 HKLM "SOFTWARE\${ProductName}" "AnugaViewerInstalled" IntCmp $0 "1" 0 post_viewer post_viewer ReadRegStr $INSTDIR HKLM "SOFTWARE\${ProductName}" "AnugaViewerDir" RMDir /r "$INSTDIR" post_viewer: ReadRegStr $INSTDIR HKLM "SOFTWARE\${ProductName}" "NetCDFDir" RMDir /r "$INSTDIR" DeleteRegKey HKCR "${ViewerExtension}" DeleteRegKey HKCR "${ViewerExtensionAlias}" DeleteRegKey HKLM "${UninstallerRegistryKey}" DeleteRegKey HKLM "SOFTWARE\${ProductName}" SectionEnd # function executed on initialization of the uninstaller Function un.onInit # prevent the uninstaller from beeing executed twice a time System::Call "kernel32::CreateMutexA(i 0, i 0, t '$(^Name)') i .n ?e" # create a mutex Pop $0 StrCmp $0 0 0 +2 Return # launch normaly if mutex could be created = no other instance running StrLen $0 "$(^Name)" IntOp $0 $0 + 1 loop: FindWindow $1 '#32770' '' 0 $1 # search the uninstallers window if another instance is already running IntCmp $1 0 +4 System::Call /NOUNLOAD "user32.dll::GetWindowText(i r1, t .r2, i r0) i.n" StrCmp $2 "$(^Name)" 0 loop # check back for correct window text System::Call "user32::SetForegroundWindow(i r1) i.n" # bring it to front if found Abort # then exit FunctionEnd #EOF