Archive: User type detection


User type detection
Hello

My NSIS script needs to care about what type of user (Administrator and User) tries to install it.

How can i decide about user type, and what else should i modify in my script, to make it user type aware?

My script:

!define DIST_DIR ".\dist"
!define RESOURCE_DIR ".\resource"
!define JRE_NAME "jre1.6.0_03"
!define JRE_ZIP_NAME "${JRE_NAME}.zip"
!define APP_NAME "MY APP"

Icon "${RESOURCE_DIR}\sample-install.ico"
UninstallIcon "${RESOURCE_DIR}\sample-uninstall.ico"

; Name of our application
Name "MY APP"

; The file to write
OutFile "setup.exe"

; Set the default Installation Directory
InstallDir "$PROGRAMFILES\${APP_NAME}"

; Set the text which prompts the user to enter the installation directory
DirText "Please choose a directory to which you'd like to install this application."

; ----------------------------------------------------------------------------------
; *************************** SECTION FOR INSTALLING *******************************
; ----------------------------------------------------------------------------------

Section "" ; A "useful" name is not needed as we are not installing separate components

; Set output path to the installation directory. Also sets the working
; directory for shortcuts
SetOutPath $INSTDIR\

File ${DIST_DIR}\myapp.jar
File .\${JRE_ZIP_NAME}
ZipDLL::extractall ${JRE_ZIP_NAME} $INSTDIR
Delete .\${JRE_ZIP_NAME}

WriteUninstaller $INSTDIR\Uninstall.exe

; ///////////////// CREATE SHORT CUTS //////////////////////////////////////

CreateDirectory "$SMPROGRAMS\${APP_NAME}"
CreateShortCut "$SMPROGRAMS\${APP_NAME}\MY App.lnk" "$INSTDIR\${JRE_NAME}\bin\javaw.exe" "-jar myapp.jar"
CreateShortCut "$SMPROGRAMS\${APP_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"

; ///////////////// END CREATING SHORTCUTS //////////////////////////////////

; //////// CREATE REGISTRY KEYS FOR ADD/REMOVE PROGRAMS IN CONTROL PANEL /////////

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "DisplayName"\
"${APP_NAME} (remove only)"

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "UninstallString" \
"$INSTDIR\Uninstall.exe"

; //////////////////////// END CREATING REGISTRY KEYS ////////////////////////////

MessageBox MB_OK "Installation was successful."

SectionEnd

; ----------------------------------------------------------------------------------
; ************************** SECTION FOR UNINSTALLING ******************************
; ----------------------------------------------------------------------------------

Section "Uninstall"
; remove all the files and folders
Delete $INSTDIR\Uninstall.exe ; delete self
Delete $INSTDIR\myapp.jar
RMDir /r $INSTDIR\${JRE_NAME}

RMDir $INSTDIR

; now remove all the startmenu links
Delete "$SMPROGRAMS\${APP_NAME}\MY App.lnk"
Delete "$SMPROGRAMS\${APP_NAME}\Uninstall.lnk"
RMDIR "$SMPROGRAMS\${APP_NAME}"

; Now delete registry keys
DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\${APP_NAME}"
DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}"

SectionEnd


I am using a

Function GetUserType
;UserInfo::GetName ;If you wanna retrieve current login
UserInfo::GetAccountType
FunctionEnd


that I use in my Function CustomizedGUIInit (to check at the beginning, but after language selection done in .onInit)

call GetUserType
pop $0
StrCmp $0 "Admin" Admin notAdmin
notAdmin:
MessageBox MB_OK|MB_ICONSTOP "Not enough privileges to run this setup.$\nThis setup is aborted."
abort
Admin:


Gal'

Thanks. I also need some conditional execution, but it is not working:

[nsis] Error: command RequestExecutionLevel not valid in Function

Function .onInit

call GetUserType
pop $0
StrCmp $0 "Admin" Admin notAdmin
notAdmin:

RequestExecutionLevel user
InstallDir "$APPDATA\${APP_NAME}"

Admin:

RequestExecutionLevel admin
InstallDir "$PROGRAMFILES\${APP_NAME}"

FunctionEnd

Function GetUserType
;UserInfo::GetName ;If you wanna retrieve current login
UserInfo::GetAccountType
FunctionEnd


That function is for Windows Vista. I can read in the manual that it is a routine to tell which level is required -"user" only in your code above- to Vista. I think that you want to set it to "admin", and I think the error is you should run RequestExecutionLevel outside a function, try it on top of your file, not inside any function.

Gal'


Right, but i still need custom RequestExecutionLevel based on the value of GetUserType. Should i remove .oninit, and make condition on top? Is that possible?


Originally posted by gberes
Right, but i still need custom RequestExecutionLevel based on the value of GetUserType.
?? Why ??

RequestExecutionLevel => it is up to you, YOU have to decide which rights your setup exe requires to complete the installation process (and if you wanna write registery keys for any user and so on... you need to be "admin").

GetUserType, it is a function that give you the current rights at runtime. This make you the ability to handle manually on XP and others the lack of privileges. But if your installer is dedicated to Vista, you might use RequestExecutionLevel instead since Vista will check for the user rights in its own and ask for admin password prior to launch your installation process.

I am not pretty sure for the Vista view since I am writting an installer for XP/2k and I don't use RequestExecutionLevel at all.

Gal'

My application can be installed by two type of account, administrator, and user.

I understand your point, but i still need to perform custom activity by user type, such as install location determination.

Function .onInit

call GetUserType
pop $0
StrCmp $0 "Admin" Admin notAdmin
notAdmin:

InstallDir "$APPDATA\${APP_NAME}"

Admin:

InstallDir "$PROGRAMFILES\${APP_NAME}"

FunctionEnd


That gives this:
[nsis] Error: command InstallDir not valid in Function


InstallDir can not be used in a function, but you can set $instdir in .onInit for example

Function .onInit
StrCmp something blah foo
user:
StrCpy $Instdir "c:\foo"
goto done
admin:
StrCpy $Instdir "c:\bar"
done:
FunctionEnd


Yep, the same error, you have to run your InstallDir outside a function. If you want to do it inside a func, try a StrCpy $INSTDIR "your_path" instead.

To suit your needs, I think the best way for you is to handle manually the privileges control: don't use RequestExecutionLevel (on Vista, you won't have the admin password pop-up... but...) or do it with the lowest privileges => useless since no password will be asked.

I advise you to manage instead you privileges level with your .onInit func using GetUserType... you can do everything you want, but having privileges escalation thanks to Vista built-in feature. Is that Okay for you ?

Gal'


Its ok, thanks.
One more thing. With the following code, Installation dir is always program files. Why?

SetOutPath $INSTDIR\ // in section


Function .onInit

call GetUserType
pop $0
StrCmp $0 "Admin" Admin notAdmin
notAdmin:

StrCpy $INSTDIR "$APPDATA\${APP_NAME}"

Admin:

StrCpy $INSTDIR "$PROGRAMFILES\${APP_NAME}"

FunctionEnd

Function GetUserType
;UserInfo::GetName ;If you wanna retrieve current login
UserInfo::GetAccountType
FunctionEnd


:D

You forgot something....


[...]
notAdmin:

StrCpy $INSTDIR "$APPDATA\${APP_NAME}"
goto end
Admin:

StrCpy $INSTDIR "$PROGRAMFILES\${APP_NAME}"

end:

FunctionEnd


Beacuse in case 1.... you also play the case 2.

Gal'

gross mistake :D