!addplugindir ".\release" !define S_NAME "UAC_ModeSelection example" !define APPNAME "UAC_Dummy_App" !define S_DEFINSTDIR_USER "$LocalAppData\${APPNAME}" !define S_DEFINSTDIR_ADMIN "$ProgramFiles\${APPNAME}" !define UNINSTALLER_FULLPATH "$InstDir\Uninstaller.exe" !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\orange-install.ico" !define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall.ico" Name "${S_NAME}" OutFile "${S_NAME}.exe" !include MUI2.nsh !include UAC.nsh !include nsDialogs.nsh !ifndef BCM_SETSHIELD !define BCM_SETSHIELD 0x0000160C !endif !define MUI_FINISHPAGE_NOAUTOCLOSE !define MUI_UNFINISHPAGE_NOAUTOCLOSE !macro BUILD_LANGUAGES !insertmacro MUI_LANGUAGE "English" !macroend /*************************************************** ** Installer ***************************************************/ !macro SetInstMode m StrCpy $InstMode ${m} call InstModeChanged !macroend !macro BUILD_INSTALLER !define MUI_COMPONENTSPAGE_NODESC !define MUI_CUSTOMFUNCTION_GUIINIT GuiInit !insertmacro MUI_PAGE_LICENSE History.txt page custom InstModeSelectionPage_Create InstModeSelectionPage_Leave !define MUI_PAGE_CUSTOMFUNCTION_PRE disableBack !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !define MUI_FINISHPAGE_RUN !define MUI_FINISHPAGE_RUN_FUNCTION FinishRun !insertmacro MUI_PAGE_FINISH var InstMode ;0=current,1=all users Function InstModeChanged SetShellVarContext CURRENT ${IfNotThen} ${Silent} ${|} StrCpy $InstDir "${S_DEFINSTDIR_USER}" ${|} ${If} $InstMode > 0 SetShellVarContext ALL ${IfNotThen} ${Silent} ${|} StrCpy $InstDir "${S_DEFINSTDIR_ADMIN}" ${|} ${EndIf} FunctionEnd Function .onInit !insertmacro UAC_PageElevation_OnInit ${If} ${UAC_IsInnerInstance} ${AndIfNot} ${UAC_IsAdmin} SetErrorLevel 0x666666 ;special return value for outer instance so it knows we did not have admin rights Quit ${EndIf} StrCpy $InstMode 0 ${IfThen} ${UAC_IsAdmin} ${|} StrCpy $InstMode 1 ${|} call InstModeChanged ${If} ${Silent} ${AndIf} $InstDir == "" ;defaults (for silent installs) SetSilent normal call InstModeChanged SetSilent silent ${EndIf} FunctionEnd Function GuiInit !insertmacro UAC_PageElevation_OnGuiInit FunctionEnd Function disableBack ${If} ${UAC_IsInnerInstance} GetDlgItem $0 $HWNDParent 3 EnableWindow $0 0 ${EndIf} FunctionEnd Function RemoveNextBtnShield GetDlgItem $0 $hwndParent 1 SendMessage $0 ${BCM_SETSHIELD} 0 0 FunctionEnd Function InstModeSelectionPage_Create !insertmacro MUI_HEADER_TEXT_PAGE "Select install type" "Blah blah blah blah" GetFunctionAddress $8 InstModeSelectionPage_OnClick nsDialogs::Create /NOUNLOAD 1018 Pop $9 ${NSD_OnBack} RemoveNextBtnShield ${NSD_CreateLabel} 0 20u 75% 20u "Blah blah blah blah select install type..." Pop $0 System::Call "advapi32::GetUserName(t.r0,*i${NSIS_MAX_STRLEN})i" ${NSD_CreateRadioButton} 0 40u 75% 15u "Single User ($0)" Pop $0 nsDialogs::OnClick $0 $8 nsDialogs::SetUserData $0 0 SendMessage $0 ${BM_CLICK} 0 0 ${NSD_CreateRadioButton} 0 60u 75% 15u "All users" Pop $2 nsDialogs::OnClick $2 $8 nsDialogs::SetUserData $2 1 ${IfThen} $InstMode <> 0 ${|} SendMessage $2 ${BM_CLICK} 0 0 ${|} push $2 ;store allusers radio hwnd on stack nsDialogs::Show pop $2 FunctionEnd Function InstModeSelectionPage_OnClick pop $1 nsDialogs::GetUserData $1 pop $1 GetDlgItem $0 $hwndParent 1 SendMessage $0 ${BCM_SETSHIELD} 0 $1 FunctionEnd Function InstModeSelectionPage_Leave pop $0 ;get hwnd push $0 ;and put it back ${NSD_GetState} $0 $9 ${If} $9 = 0 !insertmacro SetInstMode 0 ${Else} !insertmacro SetInstMode 1 ${IfNot} ${UAC_IsAdmin} GetDlgItem $9 $HWNDParent 1 System::Call user32::GetFocus()i.s EnableWindow $9 0 ;disable next button !insertmacro UAC_PageElevation_RunElevated EnableWindow $9 1 System::Call user32::SetFocus(is) ;Do we need WM_NEXTDLGCTL or can we get away with this hack? ${If} $2 = 0x666666 ;our special return, the new process was not admin after all MessageBox mb_iconExclamation "You need to login with an account that is a member of the admin group to continue..." Abort ${ElseIf} $0 = 1223 ;cancel Abort ${Else} ${If} $0 <> 0 ${If} $0 = 1062 MessageBox mb_iconstop "Unable to elevate, Secondary Logon service not running!" ${Else} MessageBox mb_iconstop "Unable to elevate, error $0" ${EndIf} Abort ${EndIf} ${EndIf} Quit ;We now have a new process, the install will continue there, we have nothing left to do here ${EndIf} ${EndIf} FunctionEnd Function FinishRun !insertmacro UAC_AsUser_ExecShell "" "calc.exe" "" "" "" FunctionEnd Section "Required Files" SectionIn RO SectionEnd Section "Start menu shortcuts" CreateShortcut "$smprograms\${APPNAME}.lnk" '"${UNINSTALLER_FULLPATH}"' SectionEnd Section Uninstaller SetOutPath - ${If} $InstMode = 0 !insertmacro CreateUninstaller "${UNINSTALLER_FULLPATH}" 0 ${Else} !insertmacro CreateUninstaller "${UNINSTALLER_FULLPATH}" 1 ${EndIf} WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" DisplayName "${APPNAME}" WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" UninstallString "${UNINSTALLER_FULLPATH}" WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" InstallLocation $InstDir WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" NoModify 1 WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" NoRepair 1 SectionEnd !macroend /*************************************************** ** Uninstaller ***************************************************/ !macro BUILD_UNINSTALLER !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES ;!insertmacro MUI_UNPAGE_FINISH Function UN.onInit !if ${BUILDUNINST} > 0 SetShellVarContext ALL !insertmacro UAC_RunElevated ${Switch} $0 ${Case} 0 ${IfThen} $1 = 1 ${|} Quit ${|} ;we are the outer process, the inner process has done its work, we are done ${IfThen} $3 <> 0 ${|} ${Break} ${|} ;we are admin, let the show go on ;fall-through and die ${Case} 1223 MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "This uninstaller requires admin privileges, aborting!" Quit ${Case} 1062 MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Logon service not running, aborting!" Quit ${Default} MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Unable to elevate , error $0" Quit ${EndSwitch} !endif FunctionEnd Section -un.Main Delete "$smprograms\${APPNAME}.lnk" Delete "${UNINSTALLER_FULLPATH}" DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" RMDir $instdir SectionEnd !macroend /***************************************************/ !macro CreateUninstaller extractTo mode !tempfile UNINSTEXE !system '"${NSISDIR}\MakeNSIS" /DBUILDUNINST=${mode} /DUNINSTEXE=${UNINSTEXE} "${__FILE__}"' = 0 !system '"${UNINSTEXE}"' = 0 File "/oname=${extractTo}" "${UNINSTEXE}.un" !delfile "${UNINSTEXE}" !delfile "${UNINSTEXE}.un" !undef UNINSTEXE !macroend !ifndef BUILDUNINST RequestExecutionLevel user !insertmacro BUILD_INSTALLER !else SilentInstall silent OutFile "${UNINSTEXE}" !if ${BUILDUNINST} > 0 RequestExecutionLevel admin !else RequestExecutionLevel user !endif !insertmacro MUI_PAGE_INSTFILES !insertmacro BUILD_UNINSTALLER Section WriteUninstaller "${UNINSTEXE}.un" SectionEnd !endif !insertmacro BUILD_LANGUAGES