Archive: UAC: CreateShortcut not created in user directory


UAC: CreateShortcut not created in user directory
Hi,

I have the problem, that I want to execute my NSIS installer with user privilegues via the UAC plugin. In my opinion I did everything right with the UAC plugin, but all shortcuts (desktop and startmenu) are not created in the user directories, but in the administrator directories.

These following lines are the most important in my opinion:

!include "UAC.nsh"


RequestExecutionLevel user


; Attempt to give the UAC plug-in a user process and an admin process.
Function .OnInit

UAC_Elevate:
!insertmacro UAC_PageElevation_RunElevated
StrCmp 1223 $0 UAC_ElevationAborted ; UAC dialog aborted by user?
StrCmp 0 $0 0 UAC_Err ; Error?
StrCmp 1 $1 0 UAC_Success ;Are we the real deal or just the wrapper?
Quit

UAC_Err:
MessageBox mb_iconstop "Unable to elevate, error $0"
Abort

UAC_ElevationAborted:
# elevation was aborted, run as normal?
MessageBox mb_iconstop "This installer requires admin access, aborting!"
Abort

UAC_Success:
StrCmp 1 $3 +4 ;Admin?
StrCmp 3 $1 0 UAC_ElevationAborted ;Try again?
MessageBox mb_iconstop "This installer requires admin access, try again"
goto UAC_Elevate

FunctionEnd


!insertmacro UAC_AsUser_Call Function CreateUserShortcuts ${UAC_SYNCREGISTERS}


Function CreateUserShortcuts
# start menu
createDirectory "$SMPROGRAMS\genialix 1x1\"
createShortCut "$SMPROGRAMS\genialix 1x1\genialix 1x1.lnk" "$INSTDIR\genialix-1x1-launcher.exe" "" "$INSTDIR\genialix.ico"
createShortCut "$SMPROGRAMS\genialix 1x1\genialix 1x1 deinstallieren.lnk" "$INSTDIR\uninstall.exe" ""

# desktop shortcut
createShortCut "$DESKTOP\genialix 1x1.lnk" "$INSTDIR\genialix-1x1-launcher.exe" "" "$INSTDIR\genialix.ico"
FunctionEnd


I also have the whole NSIS script attached, if it helps...
I used NSIS version 2.46, with UAC version 0.2.2d from here:
http://nsis.sourceforge.net/UAC_plug-in

Thanks in advance for your help!

!include "MUI2.nsh"
!include LogicLib.nsh
!include "UAC.nsh"

#required: jre 1.6
!define MIN_JAVA_MAJOR_VERSION 1
!define MIN_JAVA_MINOR_VERSION 6

#name
!define APPLICATION_NAME "genialix 1x1"

outFile "genialix-1x1-installer.exe"
Name "${APPLICATION_NAME}"
Icon "genialix.ico"
!define MUI_ICON "genialix.ico"
!define MUI_UNICON "genialix.ico"
installDir "$PROGRAMFILES\genialix 1x1"
RequestExecutionLevel user

;Get installation folder from registry if available
InstallDirRegKey HKCU "Software\genialix 1x1" ""

;Request application privileges for Windows Vista
RequestExecutionLevel admin

;--------------------------------
;Interface Settings

!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "OneHundred_NSIS_Header.bmp" #optional
!define MUI_ABORTWARNING
!define MUI_WELCOMEFINISHPAGE_BITMAP "OneHundred_NSIS_WelcomeFinishPage.bmp" #optional


;--------------------------------
;Pages

!insertmacro MUI_PAGE_WELCOME
# !insertmacro MUI_PAGE_LICENSE "${NSISDIR}\Docs\Modern UI\License.txt"
!insertmacro MUI_PAGE_LICENSE "license.txt"
!insertmacro MUI_PAGE_DIRECTORY
!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 "German"


; Attempt to give the UAC plug-in a user process and an admin process.
Function .OnInit

UAC_Elevate:
!insertmacro UAC_PageElevation_RunElevated
StrCmp 1223 $0 UAC_ElevationAborted ; UAC dialog aborted by user?
StrCmp 0 $0 0 UAC_Err ; Error?
StrCmp 1 $1 0 UAC_Success ;Are we the real deal or just the wrapper?
Quit

UAC_Err:
MessageBox mb_iconstop "Unable to elevate, error $0"
Abort

UAC_ElevationAborted:
# elevation was aborted, run as normal?
MessageBox mb_iconstop "This installer requires admin access, aborting!"
Abort

UAC_Success:
StrCmp 1 $3 +4 ;Admin?
StrCmp 3 $1 0 UAC_ElevationAborted ;Try again?
MessageBox mb_iconstop "This installer requires admin access, try again"
goto UAC_Elevate

FunctionEnd


# start default section
section

# set the installation directory as the destination for the following actions
setOutPath $INSTDIR

call jre_installation

file "genialix.ico"
file "genialix-1x1-launcher.exe"
file /r "..\..\dist\*.*"

# create the uninstaller
writeUninstaller "$INSTDIR\uninstall.exe"

!insertmacro UAC_AsUser_Call Function CreateUserShortcuts ${UAC_SYNCREGISTERS}

sectionEnd

# jre installation
function jre_installation

# read jre version from registry
ClearErrors
ReadRegStr $R1 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" "CurrentVersion"
#ReadRegStr $R0 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment\$R1" "JavaHome"
IfErrors no_jre_found

# check if java version suits our needs
Push "."
Push $R1
call SplitFirstStrPart
Pop $R0 #1st part (hopefully something like "1")
Pop $R1 #rest (hopefully something like "6")
${If} $R0 == ${MIN_JAVA_MAJOR_VERSION}
${If} $R1 < ${MIN_JAVA_MINOR_VERSION}
goto old_jre_found
${Else}
return
${EndIf}
${ElseIf} $R0 < ${MIN_JAVA_MAJOR_VERSION}
goto old_jre_found
${Else}
return
${EndIf}

MessageBox MB_OK "Fehler bei der Java-Erkennung. $\nInstallation wird ohne Java fortgesetzt."
return

# jre version could not be detected -> probably no java installed
no_jre_found:
MessageBox MB_YESNO "Für ${APPLICATION_NAME} wird Java benötigt. Auf diesem Computer wurde kein Java gefunden. $\n$\nWollen Sie es jetzt installieren?" /SD IDYES IDYES do_jre_installation
Abort

# jre version is too old
old_jre_found:
MessageBox MB_YESNO "Für ${APPLICATION_NAME} wird eine aktuelle Version von Java benötigt. $\nDas auf diesem Computer installierte Java ist jedoch veraltet. $\n$\nWollen Sie es jetzt eine aktuelle Version von Java installieren?" /SD IDYES IDYES do_jre_installation
Abort

# the actual jre installer
do_jre_installation:
file "jre-6u22-windows-i586-s.exe"
ClearErrors
ExecWait "$INSTDIR\jre-6u22-windows-i586-s.exe"
IfErrors installing_jre_error
return

# jre not installed? -> quit
installing_jre_error:
MessageBox MB_OK "Install JRE error"
Abort

functionEnd

Function SplitFirstStrPart
Exch $R0
Exch
Exch $R1
Push $R2
Push $R3
StrCpy $R3 $R1
StrLen $R1 $R0
IntOp $R1 $R1 + 1
loop:
IntOp $R1 $R1 - 1
StrCpy $R2 $R0 1 -$R1
StrCmp $R1 0 exit0
StrCmp $R2 $R3 exit1 loop
exit0:
StrCpy $R1 ""
Goto exit2
exit1:
IntOp $R1 $R1 - 1
StrCmp $R1 0 0 +3
StrCpy $R2 ""
Goto +2
StrCpy $R2 $R0 "" -$R1
IntOp $R1 $R1 + 1
StrCpy $R0 $R0 -$R1
StrCpy $R1 $R2
exit2:
Pop $R3
Pop $R2
Exch $R1 ;rest
Exch
Exch $R0 ;first
FunctionEnd

# uninstaller section start
section "uninstall"

# first, delete the uninstaller
delete "$INSTDIR\uninstall.exe"

# delete files
delete "$INSTDIR\genialix.ico"
delete "$INSTDIR\genialix-1x1-launcher.exe"
delete "$INSTDIR\OneHundred.jar"
delete "jre-6u22-windows-i586-s.exe"
RMDir "$INSTDIR"

!insertmacro UAC_AsUser_Call Function Un.CreateUserShortcuts ${UAC_SYNCREGISTERS}

# uninstaller section end
sectionEnd


Function CreateUserShortcuts
# start menu
createDirectory "$SMPROGRAMS\genialix 1x1\"
createShortCut "$SMPROGRAMS\genialix 1x1\genialix 1x1.lnk" "$INSTDIR\genialix-1x1-launcher.exe" "" "$INSTDIR\genialix.ico"
createShortCut "$SMPROGRAMS\genialix 1x1\genialix 1x1 deinstallieren.lnk" "$INSTDIR\uninstall.exe" ""

# desktop shortcut
createShortCut "$DESKTOP\genialix 1x1.lnk" "$INSTDIR\genialix-1x1-launcher.exe" "" "$INSTDIR\genialix.ico"
FunctionEnd

Function Un.CreateUserShortcuts
# start menu
delete "$SMPROGRAMS\genialix 1x1\genialix 1x1.lnk"
delete "$SMPROGRAMS\genialix 1x1\genialix 1x1 deinstallieren.lnk"
RMDir "$SMPROGRAMS\genialix 1x1\"

# desktop shortcut
delete "$DESKTOP\genialix 1x1.lnk"
FunctionEnd

Well, I can only find one problem and that's that you don't syncinstdir for your userlevel function. But that wouldn't change the location where the shortcut is created. How about if you explicitly setshellvarcontext user in the userlevel function?

Also, please do NOT post such large amounts of code in the forums. Either use pastebin or add a file attachment.


Thanks for your answer! Using setshellvarcontext seems to be a hack, I would feel better when finding out what the real problem is... And how should I use it anyway? I only found this doc and no real example:
http://nsis.sourceforge.net/Docs/Chapter4.html#4.9.7.7

Sorry for posting the whole script, I can't edit it anymore now...


Err... Why would using a proper NSIS command be a hack? Just try it and see if it works. And as you can read in the manual entry you linked, the user's context can be set by passing the parameter 'current'.

Anyway, better still, add a MessageBox to verify that the path you're passing to createshortcut is actually correct.