!include "MUI2.nsh" Name "GoldenDict" OutFile "GoldenDict-1.5.0-Install.exe" InstallDir "$PROGRAMFILES\GoldenDict" RequestExecutionLevel admin SetCompressor /final lzma Var StartMenuFolder ;-------------------------------- ;Interface Settings !define MUI_ABORTWARNING ;-------------------------------- ;Pages !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "../LICENSE.txt" !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_STARTMENU GDApplication $StartMenuFolder !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH !insertmacro MUI_UNPAGE_WELCOME !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES !insertmacro MUI_UNPAGE_FINISH ;-------------------------------- ;Languages !insertmacro MUI_LANGUAGE "English" ;first language is the default language !insertmacro MUI_LANGUAGE "French" !insertmacro MUI_LANGUAGE "German" !insertmacro MUI_LANGUAGE "Spanish" !insertmacro MUI_LANGUAGE "SpanishInternational" !insertmacro MUI_LANGUAGE "SimpChinese" !insertmacro MUI_LANGUAGE "TradChinese" !insertmacro MUI_LANGUAGE "Japanese" !insertmacro MUI_LANGUAGE "Korean" !insertmacro MUI_LANGUAGE "Italian" !insertmacro MUI_LANGUAGE "Dutch" !insertmacro MUI_LANGUAGE "Danish" !insertmacro MUI_LANGUAGE "Swedish" !insertmacro MUI_LANGUAGE "Norwegian" !insertmacro MUI_LANGUAGE "NorwegianNynorsk" !insertmacro MUI_LANGUAGE "Finnish" !insertmacro MUI_LANGUAGE "Greek" !insertmacro MUI_LANGUAGE "Russian" !insertmacro MUI_LANGUAGE "Portuguese" !insertmacro MUI_LANGUAGE "PortugueseBR" !insertmacro MUI_LANGUAGE "Polish" !insertmacro MUI_LANGUAGE "Ukrainian" !insertmacro MUI_LANGUAGE "Czech" !insertmacro MUI_LANGUAGE "Slovak" !insertmacro MUI_LANGUAGE "Croatian" !insertmacro MUI_LANGUAGE "Bulgarian" !insertmacro MUI_LANGUAGE "Hungarian" !insertmacro MUI_LANGUAGE "Thai" !insertmacro MUI_LANGUAGE "Romanian" !insertmacro MUI_LANGUAGE "Latvian" !insertmacro MUI_LANGUAGE "Macedonian" !insertmacro MUI_LANGUAGE "Estonian" !insertmacro MUI_LANGUAGE "Turkish" !insertmacro MUI_LANGUAGE "Lithuanian" !insertmacro MUI_LANGUAGE "Slovenian" !insertmacro MUI_LANGUAGE "Serbian" !insertmacro MUI_LANGUAGE "SerbianLatin" !insertmacro MUI_LANGUAGE "Arabic" !insertmacro MUI_LANGUAGE "Farsi" !insertmacro MUI_LANGUAGE "Hebrew" !insertmacro MUI_LANGUAGE "Indonesian" !insertmacro MUI_LANGUAGE "Mongolian" !insertmacro MUI_LANGUAGE "Luxembourgish" !insertmacro MUI_LANGUAGE "Albanian" !insertmacro MUI_LANGUAGE "Breton" !insertmacro MUI_LANGUAGE "Belarusian" !insertmacro MUI_LANGUAGE "Icelandic" !insertmacro MUI_LANGUAGE "Malay" !insertmacro MUI_LANGUAGE "Bosnian" !insertmacro MUI_LANGUAGE "Kurdish" !insertmacro MUI_LANGUAGE "Irish" !insertmacro MUI_LANGUAGE "Uzbek" !insertmacro MUI_LANGUAGE "Galician" !insertmacro MUI_LANGUAGE "Afrikaans" !insertmacro MUI_LANGUAGE "Catalan" !insertmacro MUI_LANGUAGE "Esperanto" ;-------------------------------- ;Installer Sections Section SetOutPath "$INSTDIR" CreateDirectory $INSTDIR\imageformats SetOutPath $INSTDIR\imageformats File ..\imageformats\* CreateDirectory $INSTDIR\codecs SetOutPath $INSTDIR\codecs File ..\codecs\* CreateDirectory $INSTDIR\x64 SetOutPath $INSTDIR\x64 File ..\x64\* CreateDirectory $INSTDIR\locale SetOutPath $INSTDIR\locale File ..\locale\* CreateDirectory $INSTDIR\content CreateDirectory $INSTDIR\content\morphology SetOutPath $INSTDIR\content\morphology File ..\content\morphology\* SetOutPath $INSTDIR File ..\*.dll File ..\LICENSE.txt File /oname=$INSTDIR\GoldenDict.exe ..\goldendict.exe WriteUninstaller "$INSTDIR\Uninstall.exe" !insertmacro MUI_STARTMENU_WRITE_BEGIN GDApplication SetShellVarContext all CreateDirectory "$SMPROGRAMS\$StartMenuFolder" CreateShortCut "$SMPROGRAMS\$StartMenuFolder\GoldenDict.lnk" "$INSTDIR\GoldenDict.exe" CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\Uninstall.exe" !insertmacro MUI_STARTMENU_WRITE_END WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\GoldenDict" \ "DisplayName" "GoldenDict" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\GoldenDict" \ "UninstallString" "$INSTDIR\Uninstall.exe" SectionEnd !define PROGRAM_NAME "GoldenDict" Function .onInit !insertmacro MUI_LANGDLL_DISPLAY ReadRegStr $R0 HKLM \ "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGRAM_NAME}" \ "UninstallString" StrCmp $R0 "" done MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \ "${PROGRAM_NAME} is already installed. $\n$\nClick `OK` to remove the \ previous version or `Cancel` to cancel this upgrade." \ IDOK uninst Abort ;Run the uninstaller uninst: ClearErrors ExecWait '$R0 /NODELCFG=1 _?=$INSTDIR' ;Do not copy the uninstaller to a temp file IfErrors no_remove_uninstaller done ;You can either use Delete /REBOOTOK in the uninstaller or add some code ;here to remove the uninstaller. Use a registry key to check ;whether the user has chosen to uninstall. If you are using an uninstaller ;components page, make sure all sections are uninstalled. no_remove_uninstaller: done: FunctionEnd ;-------------------------------- ;Uninstaller Section !define WND_CLASS "QWidget" !define WND_TITLE "GoldenDict" !define TO_MS 2000 !define SYNC_TERM 0x00100001 !include WinMessages.nsh LangString termMsg ${LANG_ENGLISH} "Installer cannot stop running ${WND_TITLE}.$\nDo you want to terminate process?" LangString stopMsg ${LANG_ENGLISH} "Stopping ${WND_TITLE}" !macro TerminateApp Push $0 ; window handle Push $1 Push $2 ; process handle DetailPrint "$(stopMsg)" FindWindow $0 '${WND_CLASS}' '' IntCmp $0 0 done System::Call 'user32.dll::GetWindowThreadProcessId(i r0, *i .r1) i .r2' System::Call 'kernel32.dll::OpenProcess(i ${SYNC_TERM}, i 0, i r1) i .r2' SendMessage $0 ${WM_CLOSE} 0 0 /TIMEOUT=${TO_MS} System::Call 'kernel32.dll::WaitForSingleObject(i r2, i ${TO_MS}) i .r1' terminate: System::Call 'kernel32.dll::TerminateProcess(i r2, i 0) i .r1' close: System::Call 'kernel32.dll::CloseHandle(i r2) i .r1' ; Make sure all process files are released Sleep 2000 done: Pop $2 Pop $1 Pop $0 !macroend Function un.StrStr /*After this point: ------------------------------------------ $R0 = SubString (input) $R1 = String (input) $R2 = SubStringLen (temp) $R3 = StrLen (temp) $R4 = StartCharPos (temp) $R5 = TempStr (temp)*/ ;Get input from user Exch $R0 Exch Exch $R1 Push $R2 Push $R3 Push $R4 Push $R5 ;Get "String" and "SubString" length StrLen $R2 $R0 StrLen $R3 $R1 ;Start "StartCharPos" counter StrCpy $R4 0 ;Loop until "SubString" is found or "String" reaches its end loop: ;Remove everything before and after the searched part ("TempStr") StrCpy $R5 $R1 $R2 $R4 ;Compare "TempStr" with "SubString" StrCmp $R5 $R0 done ;If not "SubString", this could be "String"'s end IntCmp $R4 $R3 done 0 done ;If not, continue the loop IntOp $R4 $R4 + 1 Goto loop done: /*After this point: ------------------------------------------ $R0 = ResultVar (output)*/ ;Remove part before "SubString" on "String" (if there has one) StrCpy $R0 $R1 `` $R4 ;Return output to user Pop $R5 Pop $R4 Pop $R3 Pop $R2 Pop $R1 Exch $R0 FunctionEnd ; GetParameters ; input, none ; output, top of stack (replaces, with e.g. whatever) ; modifies no other variables. Function un.GetParameters Push $R0 Push $R1 Push $R2 Push $R3 StrCpy $R2 1 StrLen $R3 $CMDLINE ;Check for quote or space StrCpy $R0 $CMDLINE $R2 StrCmp $R0 '"' 0 +3 StrCpy $R1 '"' Goto loop StrCpy $R1 " " loop: IntOp $R2 $R2 + 1 StrCpy $R0 $CMDLINE 1 $R2 StrCmp $R0 $R1 get StrCmp $R2 $R3 get Goto loop get: IntOp $R2 $R2 + 1 StrCpy $R0 $CMDLINE 1 $R2 StrCmp $R0 " " get StrCpy $R0 $CMDLINE "" $R2 Pop $R3 Pop $R2 Pop $R1 Exch $R0 FunctionEnd Function un.GetParameterValue Exch $R0 ; get the top of the stack(default parameter) into R0 Exch ; exchange the top of the stack(default) with ; the second in the stack(parameter to search for) Exch $R1 ; get the top of the stack(search parameter) into $R1 ;Preserve on the stack the registers used in this function Push $R2 Push $R3 Push $R4 Push $R5 Strlen $R2 $R1+2 ; store the length of the search string into R2 Call un.GetParameters ; get the command line parameters Pop $R3 ; store the command line string in R3 # search for quoted search string StrCpy $R5 '"' ; later on we want to search for a open quote Push $R3 ; push the 'search in' string onto the stack Push '"/$R1=' ; push the 'search for' Call un.StrStr ; search for the quoted parameter value Pop $R4 StrCpy $R4 $R4 "" 1 ; skip over open quote character, "" means no maxlen StrCmp $R4 "" "" next ; if we didn't find an empty string go to next # search for non-quoted search string StrCpy $R5 ' ' ; later on we want to search for a space since we ; didn't start with an open quote '"' we shouldn't ; look for a close quote '"' Push $R3 ; push the command line back on the stack for searching Push '/$R1=' ; search for the non-quoted search string Call un.StrStr Pop $R4 ; $R4 now contains the parameter string starting at the search string, ; if it was found next: StrCmp $R4 "" check_for_switch ; if we didn't find anything then look for ; usage as a command line switch # copy the value after /$R1= by using StrCpy with an offset of $R2, # the length of '/OUTPUT=' StrCpy $R0 $R4 "" $R2 ; copy commandline text beyond parameter into $R0 # search for the next parameter so we can trim this extra text off Push $R0 Push $R5 ; search for either the first space ' ', or the first ; quote '"' ; if we found '"/output' then we want to find the ; ending ", as in '"/output=somevalue"' ; if we found '/output' then we want to find the first ; space after '/output=somevalue' Call un.StrStr ; search for the next parameter Pop $R4 StrCmp $R4 "" done ; if 'somevalue' is missing, we are done StrLen $R4 $R4 ; get the length of 'somevalue' so we can copy this ; text into our output buffer StrCpy $R0 $R0 -$R4 ; using the length of the string beyond the value, ; copy only the value into $R0 goto done ; if we are in the parameter retrieval path skip over ; the check for a command line switch ; See if the parameter was specified as a command line switch, like '/output' check_for_switch: Push $R3 ; push the command line back on the stack for searching Push '/$R1' ; search for the non-quoted search string Call un.StrStr Pop $R4 StrCmp $R4 "" done ; if we didn't find anything then use the default StrCpy $R0 "" ; otherwise copy in an empty string since we found the ; parameter, just didn't find a value done: Pop $R5 Pop $R4 Pop $R3 Pop $R2 Pop $R1 Exch $R0 ; put the value in $R0 at the top of the stack FunctionEnd Section "Uninstall" !insertmacro TerminateApp Push "NODELCFG" ; push the search string onto the stack Push "0" ; push a default value onto the stack Call un.GetParameterValue Pop $2 StrCmp $2 "1" skip_cfg MessageBox MB_YESNO "Delete all configuration data and index? This will save a lot of space, but at the expense of reconfiguring and reindexing everything if GoldenDict is ever installed again." IDNO skip_cfg RMDir /r $APPDATA\GoldenDict skip_cfg: SetShellVarContext all !insertmacro MUI_STARTMENU_GETFOLDER GDApplication $StartMenuFolder ; This file is auto-generated !include "uninst.nsh" Delete "$INSTDIR\Uninstall.exe" RMDir "$INSTDIR" DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\GoldenDict" SectionEnd