Monday, September 24, 2012

How to make a Per-User installation with NSIS

I've been doing some researching on how to make it possible for users to install applications without administrator credentials.

There is a lot of good samples on how to make an UAC compatible installer with NSIS. But almost all the samples are made for forcing the user to run the setup as administrator, for example in the NSIS documentation.

After a lot of googling I finally found this question on the forum and the answer was exactly what I was searching for.

Key part of the script is were the $instdir is constructed:

!define FOLDERID_UserProgramFiles {5CD7AEE2-2219-4A67-B85D-6C9CE15660CB}
!define KF_FLAG_CREATE 0x00008000
!include LogicLib.nsh
!include WinVer.nsh
!include MUI2.nsh
Var SMDir ;Start menu folder
Function .onInit
;Default $Instdir (UserProgramFiles is %LOCALAPPDATA%\Programs by default, so we use that as our default)
StrCpy $0 "$LocalAppData\Programs"
;Make sure we don't overwrite $Instdir if specified on the command line or from InstallDirRegKey
${If} $Instdir == ""
        ${If} ${IsNT}
                ;Win7 has a per-user programfiles known folder and this could be a non-default location?
                System::Call 'Shell32::SHGetKnownFolderPath(g "${FOLDERID_UserProgramFiles}",i ${KF_FLAG_CREATE},i0,*i.r2)i.r1'
                ${If} $1 == 0
                        System::Call '*$2(&w${NSIS_MAX_STRLEN} .r1)'
                        StrCpy $0 $1
                        System::Call 'Ole32::CoTaskMemFree(ir2)'
                ;Everyone is admin on Win9x, so falling back to $ProgramFiles is ok
                ${IfThen} $LocalAppData == "" ${|} StrCpy $0 $ProgramFiles ${|}
        StrCpy $Instdir "$0\${APPNAME}"

No comments: