Archive: Installer doesn't delete icons in Start Menu Group


Installer doesn't delete icons in Start Menu Group
  Hello everyone and huge thanks to NSIS community for doing a great job.

The project I'm working in is using NSIS and recently it was found that uninstaller doesn't do it's job correctly. Our installer supports multi user installation mode. The problem is that the uninstaller doesn't delete icons on the desktop and in the start menu group when installing application for the current user. I've found that the reason of it is that $SMPROGRAMS == AllUsers.

Here is the code:

...
!define PRODUCT_UNINST_ROOT_KEY "SHCTX"

!define MULTIUSER_EXECUTIONLEVEL Highest
!define MULTIUSER_MUI
!define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY
!insertmacro MULTIUSER_PAGE_INSTALLMODE
...
Section Uninstall
...
#$SMPROGRAMS points to AllUsers
RMDir /r "$SMPROGRAMS\${MANUFACTURER}\${PRODUCT_NAME}$suffix"
RMDir "$SMPROGRAMS\${MANUFACTURER}"
..
SectionEnd

Do I need to set the context of $SMPROGRAMS manually. If yes than how do I get the installation mode used in installer?
Can someone help me please? I would appreciate it very much.

p.s: sorry for my English, i know it's not perfect :)


I'm confused, are you trying to remove the shortcuts during install? The Uninstall section is used for creating the uninstaller (use WriteUninstaller to make the uninstaller .exe, placed in the installer code), uninstall sections aren't executed in the installer. Otherwise you use SetShellVarContext before using $SMPROGRAMS or other shell folders to specify current or all users.


Thanks for your reply, redxii.
No, I don't try to remove shortcuts during the install process. Section 'Uninstall' is used for the uninstaller. I suppose that when user installs the application, installer writes to registry depending on what install mode has been chosen. It will write to HKLM if install mode is 'all users' or to HKCU is it's only for current user. Then, when
uninstaller is executed I suppose it should define how to initialize $SMPROGRAMS by itself. Otherwise, if it doesn't I need to implement some dummy logic like:

!if ${ROOT} == 'HKLM'
SetShellVarContext all
!else if ${ROOT} == 'HKCU'
SetShellVarContext current

In this case, how do I know the registry root of the installed application?


The value of $MultiUser.InstallMode will be AllUsers or CurrentUser. I guess we need a SetShellVarContext push and SetShellVarContext pop.

Stu


I have been thinking about the need for something like this also, it might be a good idea to be able to push/pop all the settings (SetShellVarContext,SetDetailsPrint,SetRegView etc)


Thanks, Afrow UK! Unfortunetely that didn't help me ...
Here is my code:

!define MULTIUSER_EXECUTIONLEVEL Highest
!define MULTIUSER_INSTALLMODE_COMMANDLINE

#if uncomment this line $MultiUser.InstallMode will always be == 'CurrentUser'
#!define MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER

!define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY "Software\${MANUFACTURER}\${PRODUCT_NAME}$suffix"
!define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME "Install_Dir"
!define MULTIUSER_INSTALLMODE_INSTDIR "${PRODUCT_NAME}$suffix"
!define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY "Software\${MANUFACTURER}\${PRODUCT_NAME}$suffix"
!define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME "Install_Mode"
!define MULTIUSER_MUI
...
Section Uninstall
...
${If} $MultiUser.InstallMode == 'AllUsers'
SetShellVarContext all
${ElseIf} $MultiUser.InstallMode == 'CurrentUser'
SetShellVarContext current
${EndIf}

RMDir /r "$SMPROGRAMS\${MANUFACTURER}\${PRODUCT_NAME}$suffix"
RMDir "$SMPROGRAMS\${MANUFACTURER}"
..
SectionEnd.

Perhaps I forgot something to do...


I think you misunderstand. You just need to SetShellVarContext current before deleting the shortcuts. I posted what I did because you may want to know what to set back with SetShellVarContext afterwards.

Stu


Hello, I have a similar problem. I'm not quite following what the solution is though from this thread. Any chance you could go in greater detail.

For me, it's slightly different. Everything in my installer works, except for the uninstalling for the start menu shortcut. The other shortcuts (quciklaunch and desktop) are removed no problem, along with the core of the mod.

For reference here is the code I am using (well the bits that are pertinant):

...
Var INSTDIR1 ; Mods
Var StartMenuFolder


...
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder


  Section "Start Menu Shortcut" Section4
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
!insertmacro MUI_STARTMENU_WRITE_END
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\${NAME}.lnk" "$INSTDIR1\Civ4BeyondSword.exe" ...
SectionEnd


  Section "Uninstall"

...
;Delete Start Menu Shortcut
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder
Delete "$SMPROGRAMS\$StartMenuFolder\${NAME}.lnk"
RMDir "$SMPROGRAMS\$StartMenuFolder"
...
SectionEnd



Now I can't at all figure out what's wrong with that. It installs fine, everything in this script works (even the optional add on stuff I have in other parts of the code), just the danged uninstaller refuses to remove the Start Menu shortcut. (also I replaced the icon stuff and beginning of the uninstall section with a ... because it was running off the screen, and works fine)

Anyone have any idea how to fix this?

Well I've split the uninstaller into seperate sections, and added:

SetShellVarContext "current"

To both the onInit and un.onInit (also tried SetShellVarContext "all"), and still no dice.

Anyone have any clue what is wrong with my Uninstaller? Everything works except the blasted Start Menu refuses to be deleted. :hang:

Here is my unistaller code if that helps:

;Uninstaller Section

Section "un.Core" SecUnCore

;Delete Files
RMDir /r "$0\${MOD_LOC}\*.*"
;Remove the installation directory
RMDir "$0\${MOD_LOC}"
;Delete Desktop Shortcut
Delete "$DESKTOP\${NAME}.lnk"
;Delete Quicklaunch Shortcut
Delete "$QUICKLAUNCH\${SHORT_NAME}.lnk"
SectionEnd

Section "-un.StartMenu" SecUnStartMenu

;Delete Start Menu Shortcut
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder
Delete "$SMPROGRAMS\$StartMenuFolder\${NAME}.lnk"
RMDir "$SMPROGRAMS\$StartMenuFolder"
SectionEnd

Section "-un.Registry" SecUnRegistry

DeleteRegValue "${MOD_REG_ROOT}" "Software\${MOD_LOC}" "Start Menu"
DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${MOD_LOC}"
SectionEnd

Section "-un.Uninstaller" SecUnUninstaller

# delete uninstaller
Delete "$INSTDIR\Uninstall.exe"
SectionEnd

Function un.onInit

;get mod install path of from the registy
SetShellVarContext "current"
ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${MOD_LOC}" "ModInstDir"
FunctionEnd


I've searched and searched, and been getting help from a programmer who is pretty versed in the NSIS installer on the CivFanatics forums, and no clues come up. It just doesn't work...

:(

Also one thing that might help would be to have a print statement to tell me what exactly the uninstaller is trying to do, that causes it to fail. Is there anyway to set up print statements in NSIS?

Well I was able to get logging to work (with some help). The issue is that when you select the folder to install the start menu to, it doesn't relate this information.

$StartMenuFolder should be returning SELECTEDFOLDER/${MOD_LOC}, but instead only returns ${MOD_LOC}

I thought this was the whole purpose of
MUI_STARTMENU_GETFOLDER Application $StartMenuFolder

Anyone know how to get it to pull the selected folder the user chooses when installing?


Man this is driving me nuts, I've been hammering away at it all day. My head is about to explode. I can set up another variable, like so:

  Section "Start Menu Shortcut" Section4
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
CreateShortCut "$SMPROGRAMS\$StartMenuFolder ...
!insertmacro MUI_STARTMENU_WRITE_END
StrCpy $StartMenuFolder1 "$SMPROGRAMS\$StartMenuFolder"
!define START_MENU_FOLDER "$StartMenuFolder1"
SectionEnd


But there seems to be no way to reference it in the uninstaller. Everytime I do, it just comes up blank if I check it. Everything I try I'm just stuck with this in the Install section, with no way to reference it in the uninstall section....

Well I tried a really hacky work around, that I'm not sure how or why it failed. Basically I had it write the Variable to a text file it would create on install. This worked, and the document contained the correct path. Then I set it to read that file in the uninstaller. For some reason if I used a user variable, the script failed to compile. If I used one of the default variables like $R1, it compiled, but there was nothing inside it after it was told to read the file. So strange, I was sure that would work. And it's not like Read and Write code is hard, I can't see what's wrong with it (or why using a user variable would fail to compile, but using a default variable would not). For reference this is what I mean:

  !define START_MENU_HACK "StartMenuHack.txt"  ;Do not change this block
...


Var HackStartMenu

...

StrCpy $StartMenuFolder1 "$SMPROGRAMS\$StartMenuFolder"
FileOpen $4 "$INSTDIR\Mods\${MOD_LOC}\${START_MENU_HACK}" w
FileWrite $4 "$StartMenuFolder1"
FileClose $4


Above all works, was checked, it wrote the file with the correct path.

    FileOpen $R4 "$INSTDIR\Mods\${MOD_LOC}\${START_MENU_HACK}" r
FileRead $R4 $HackStartMenu
FileClose $R4
Delete "$HackStartMenu\${NAME}.lnk"
RMDir "$HackStartMenu"

Now the above failed to compile. Complaiend about the FileRead $R4 $HackStartMenu, and said something about the user variable. But the strange thing was using $R2 compiled. But when I checked what was inside of it, it just came out blank. And I did move this to the top of the uninstall functions to make sure the folder wasn't deleted before it had a chance to read it.

I think I'm out of ideas now. Help.

Got it to work finally. I had to write the StartMenu path to the registry. Now just one minor detail left, but guess I'll start a new thread on it.


I was about to go onto what I meant earlier but then I've realised what your problem is. If you'd read the Multi User readme properly you would have saved yourself a lot of hassle.


!define MULTIUSER_EXECUTIONLEVEL Highest
!include MultiUser.nsh

...

Function .onInit
!insertmacro MULTIUSER_INIT
FunctionEnd

Function un.onInit
!insertmacro MULTIUSER_UNINIT
FunctionEnd


Stu

Hi Afrow UK

I'd like to resume this thread, as I've got some problems too. I worked through the Multi User readme, but still don't get it.

I'll describe two scenarios, in both of which I am an admin user on XP.
1:
Install the application "for anyone using this computer". Shortcuts are created in C:\Documents and Settings\All Users\Startmenu\Programs\MyApp
Now I execute the uninstaller and everything (including shortcuts) is removed as expected.

2:
Install the application "just for me". Shortcuts are created in C:\Documents and Settings\myUser\Startmenu\Programs\MyApp
Now I execute the uninstaller but the shortcuts won't get deleted. The uninstaller tries to remove shortcuts in C:\Documents and Settings\All Users\Startmenu\Programs\MyApp, but there are none.

I assume the default "installation mode" in the uninstaller is "AllUsers", if the uninstaller is executed by an admin.

I see two solutions:


Is there a simpler solution? Or I am completely of the track? :igor:

Thanks,
Remo

The 2nd solution is the correct one (I believe MultiUser will do it for you if you set the correct defines) Or for my take on this: http://www.nsis.pastebin.com/PmiY8DuZ


I am trying to tailor http://www.nsis.pastebin.com/PmiY8DuZ to install a java app with several .jar libs and a dll. After making the changes I got the nsis compile warning:

uninstall function "un.StrStr" not referenced - zeroing code (0-33) out
So I tried http://www.nsis.pastebin.com/PmiY8DuZ no changes but got the same warning. Anyone able to point me in the right direction?

Originally posted by Anders
The 2nd solution is the correct one (I believe MultiUser will do it for you if you set the correct defines) Or for my take on this: http://www.nsis.pastebin.com/PmiY8DuZ

Originally posted by JackN
After making the changes I got the nsis compile warning:
Originally Posted by NSIS uninstall function "un.StrStr" not referenced - zeroing code (0-33) out
That warning is fairly benign (thus being a warning, rather than an error).

The String Functions header uses Functions for some of its musclework. Functions can't be shared between Installer and Uninstaller, so both are defined when you use ${StrStr} to initialize the functions.

If you then subsequently not actually call the uninstaller version of that Function anywhere from the uninstaller, NSIS will throw that warning out there.

Unless you really, really need to save a few bytes (those zeroes compress nicely, of course), I wouldn't worry about it.

Uninstaller still does not delete icons in Start Menu Group or from the desktop. Do I need to delete these items explicitly? Do I need to define MUI_FINISHPAGE_RUN? This is the output from the installer followed by a script modified from http://www.nsis.pastebin.com/PmiY8DuZ:

Delete file: C:\Program Files (x86)\MyApp\MyApp.ico
Delete file: C:\Program Files (x86)\MyApp\MyApp.jar
Delete file: C:\Program Files (x86)\MyApp\lib\jcommon-1.0.16.jar
Delete file: C:\Program Files (x86)\MyApp\lib\jfreechart-1.0.13.jar
Delete file: C:\Program Files (x86)\MyApp\lib\Serialio.jar
Remove folder: C:\Program Files (x86)\MyApp\lib\
Delete file: C:\Program Files (x86)\MyApp\uninstall.exe
Remove folder: C:\Program Files (x86)\MyApp\
Completed

"MyApp"

>!define REGUINSTKEY "{82e9dffd-fcec-4ba6-b912-a595644cf080}" ; guidgen.com

>!include x64.nsh

OutFile "Setup_${APPNAME}.exe"
>Name "${APPNAME}"

>!define MULTIUSER_EXECUTIONLEVEL Highest
>!define MULTIUSER_INSTALLMODE_COMMANDLINE
>!define MULTIUSER_INSTALLMODE_InstDir "${APPNAME}"

>Var SMDir ;Start menu folder

>!define MULTIUSER_MUI
>!include MUI2.nsh
>!include MultiUser.nsh

>!macro WriteUninstData name data
push "${data}"
>push "${name}"
>call WriteUninstData
>!macroend

>!macro ReadUninstData outvar name
push "${name}"
>call un.ReadUninstData
>!if "${outvar}" != ""
>pop ${outvar}
!endif
!macroend

>Function .onInit
>!insertmacro MULTIUSER_INIT
FunctionEnd

>Function un.onInit
>;MULTIUSER_UNINIT does NOT do The Right Thing(TM), so we roll our own
>!insertmacro MULTIUSER_INIT_TEXTS
UserInfo
::GetAccountType
Pop $MultiUser.Privileges
>!insertmacro ReadUninstData $1 IMode
>${If} $1 = 0
call un.MultiUser.InstallMode.CurrentUser
>${Else}
${If}$MultiUser.Privileges != Admin
MessageBox MB_ICONSTOP "$(^Name)${MULTIUSER_INIT_TEXT_ADMINREQUIRED}"
SetErrorLevel 740 ;ERROR_ELEVATION_REQUIRED
Quit
${EndIf}
call un.MultiUser.InstallMode.AllUsers
>${EndIf}
>FunctionEnd

>!insertmacro MUI_PAGE_WELCOME
>!insertmacro MULTIUSER_PAGE_INSTALLMODE
>#!insertmacro MUI_PAGE_COMPONENTS ;This example does not have separate components
>!insertmacro MUI_PAGE_DIRECTORY
>!insertmacro MUI_PAGE_STARTMENU 0 $SMDir
>!insertmacro MUI_PAGE_INSTFILES
>###TODO:!define MUI_FINISHPAGE_RUN "$InstDir\MyApp.exe"
>!define MUI_PAGE_CUSTOMFUNCTION_SHOW PageFinShow
>!insertmacro MUI_PAGE_FINISH

>!insertmacro MUI_UNPAGE_WELCOME
>!insertmacro MUI_UNPAGE_CONFIRM
>!insertmacro MUI_UNPAGE_INSTFILES

>!insertmacro MUI_LANGUAGE English

>Function PageFinShow
>!ifdef MUI_FINISHPAGE_RUN
>;When installmode != CurrentUser, we could end up running something as the wrong user...
${If}$MultiUser.InstallMode != CurrentUser
SendMessage $mui.FinishPage.Run ${BM_SETCHECK} 0 0
>!if 1
EnableWindow $mui.FinishPage.Run 0
>!else
ShowWindow $mui.FinishPage.Run 0
>!endif
${EndIf}
!endif
>FunctionEnd


Section "Required Files"
>SectionIn RO
SetOutPath $InstDir
WriteUninstaller "$InstDir\uninstall.exe"
>;Save install mode
StrCpy$1 "0"
>${IfThen} $MultiUser.InstallMode == AllUsers ${|} StrCpy $1 "1" ${|}
!insertmacro WriteUninstData IMode $1

File${APPNAME}.ico
File dist${APPNAME}.jar
CreateDirectory "$InstDir\lib"
>File /oname=libjcommon-1.0.16.jar distlibjcommon-1.0.16.jar
File/oname=libjfreechart-1.0.13.jar distlibjfreechart-1.0.13.jar
File/oname=libSerialio.jar distlibSerialio.jar
WriteUninstaller $InstDirUninstall.exe
>; Check OS for proper jspWin.dll
>${If} ${RunningX64}
File /oname=$SYSDIRjspWin.dll dll64bjspWin.dll
>${Else}
File /oname=$SYSDIRjspWin.dll dll32bjspWin.dll
>${EndIf}

;Check for Java Runtime Environment (JRE)
${If} ${RunningX64}
${DisableX64FSRedirection}
${Unless} ${FileExists} "$SYSDIR\javaw.exe"
ExecWait '"jre-6u22-windows-x64.exe"'
${EndUnless}
${EnableX64FSRedirection}
${Else}
${Unless} ${FileExists} "$SYSDIR\javaw.exe"
ExecWait '"jre-6u22-windows-i586-s.exe"'
${EndUnless}
${EndIf}
>WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${REGUINSTKEY}" UninstallString '"$InstDir\uninstall.exe"'
>WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${REGUINSTKEY}" DisplayName "${APPNAME}"
>SectionEnd

Section-StartMenu
>!insertmacro MUI_STARTMENU_WRITE_BEGIN 0
CreateDirectory "$SMPrograms\$SMDir"
>###TODO: CreateShortcut "$SMPrograms\$SMDir\${APPNAME}.lnk" '"$InstDir\MyApp.exe"'
>CreateDirectory "$SMPrograms\$SMDir"
>CreateShortCut "$SMPrograms\$SMDir\${APPNAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${APPNAME}.jar" "$INSTDIR\${APPNAME}.ico"
>CreateShortCut "$SMPrograms\$SMDir\Uninstall ${APPNAME}.lnk" "$INSTDIR\Uninstall.exe" "$INSTDIR\${APPNAME}.ico"
>CreateShortCut "$DESKTOP\${APPNAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${APPNAME}.jar" "$INSTDIR\${APPNAME}.ico"
>;We need to save the startmenu folder so we can remove the shortcut in the uninstaller
>!insertmacro WriteUninstData SMDir $SMDir
>!insertmacro MUI_STARTMENU_WRITE_END
SectionEnd

Section Uninstall
>!insertmacro ReadUninstData $SMDir SMDir
>${If} $InstDir != ""
Delete "$InstDir\${APPNAME}.ico"
Delete "$InstDir\${APPNAME}.jar"
RMDir /r "$InstDir\lib"
>${EndIf}
${If}$SMDir != ""
Delete "$SMPrograms\$SMDir\${APPNAME}.lnk"
RMDir "$SMPrograms\$SMDir"
>${EndIf}
>DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${REGUINSTKEY}"
>Delete "$InstDir\uninstall.exe"
>RMDir "$InstDir"
>Delete "$DESKTOP\MyApp.lnk"
>SectionEnd

>Function WriteUninstData
Exch$1
push$0
Exch 2
FileOpen$0 "$InstDir\uninstall.exe" a
FileSeek$0 0 END
FileWrite$0 "$\n$1>"
>pop $1
FileWrite$0 $1
FileClose$0
pop$1
pop$0
FunctionEnd

>Function Un.ReadUninstData
Exch$9
Push$0
Push$1
Push$2
Push$3
FileOpen$0 "$EXEPATH" r
StrCpy$3 2
>${Do}
IntOp $3 $3 + 1
FileSeek$0 -$3 END $1
${If} $3 > 9999 ;${If} $1 < 33000
StrCpy$9 "" ;failed
${Break}
${EndIf}
FileRead $0 $1
StrLen$2 $9
IntOp$2 $2 + 1
StrCpy$2 $1 $2
${If} $2 == "$9>"
StrLen $2 $9
IntOp$2 $2 + 1
StrCpy$9 $1 "" $2
${Do}
StrCpy $1 $9 1 -1
${If} $1 != "$\n"
${AndIf} $1 != "$\r"
${Break}
${EndIf}
StrCpy $9 $9 -1
${Loop}
${Break}
${EndIf}
${Loop}
>pop $3
pop$2
pop$1
pop$0
Exch$9
FunctionEnd
>

Just off the bat.. since you are using MultiUser for a mixed admin/non-admin install are you checking for the correct context? $SMPrograms will either be the currently logged in user's start menu if SetShellVarContext is set to 'current' (default) and it looks as if you are intending to remove all users' start menu. The same goes for $DESKTOP, its location too will depend on SetShellVarContext.

One way is to check a string in HKCU or HKLM to see which exists, then set un.MultiUser.InstallMode.AllUsers or un.MultiUser.InstallMode.CurrentUser accordingly. You have to check HKLM and HKCU explicitly you can't use SHCTX.


The warning is there because multiuser.nsh wants it, but since its uninstaller handling is broken (IMHO) I use some custom stuff and the function that uses un.StrStr never gets called. I'm guessing you could !define UnStrStr_INCLUDED before including multiuser.nsh and then undef it again.

The normal way to deal with a problem like this is to messagebox the path in the uninstaller and make sure it is correct like redxii suggests.

But there is a bigger problem here, why are you using a dual mode script (single and all users) when you are installing files in $sysdir, only admins can do that so normal users will not be able to install without errors!

As a final note, adding a desktop shortcut in the startmenu section is well, not kind to your users, just add a desktop shortcut section and a components page


Ok: back to basics since I need to complete this. I don't need MultiUser or Admin, I was just following the example in http://www.nsis.pastebin.com/PmiY8DuZ hoping to get to a quick solution. I've gone back to something simpler that installs properly but uninstall is only partial. SMPrograms icons are still not being deleted. I have been programming in embedded environments for some time but I am very new to application programming and desktop environments. I am developing on Vista 64 but need to target XP and Vista 32 and 64 installs. I don't need all the bells and whistles in this 1.0 distribution but it would be nice if I could get it to uninstall properly. What is the simplest method to repair the uninstall to include SMPrograms?

Install details:

Output folder: C:\Program Files (x86)\MyApp
Extract: MyApp.ico... 100%
Extract: MyApp.jar... 100%
Create folder: C:\Program Files (x86)\MyApp\lib
Extract: lib\jcommon-1.0.16.jar... 100%
Extract: lib\jfreechart-1.0.13.jar... 100%
Extract: lib\Serialio.jar... 100%
Created uninstaller: C:\Program Files (x86)\MyApp\Uninstall.exe
Extract: C:\Windows\system32\jspWin.dll... 100%
Create folder: C:\Users\jackn\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\MyApp
Create shortcut: C:\Users\jackn\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\MyApp\MyApp.lnk
Create shortcut: C:\Users\jackn\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\MyApp\Uninstall MyApp.lnk
Completed
Uninstall details:

Delete file: C:\Program Files (x86)\MyApp\MyApp.ico
Delete file: C:\Program Files (x86)\MyApp\MyApp.jar
Delete file: C:\Program Files (x86)\MyApp\Uninstall.exe
Delete file: C:\Program Files (x86)\MyApp\lib\jcommon-1.0.16.jar
Delete file: C:\Program Files (x86)\MyApp\lib\jfreechart-1.0.13.jar
Delete file: C:\Program Files (x86)\MyApp\lib\Serialio.jar
Remove folder: C:\Program Files (x86)\MyApp\lib\
Remove folder: C:\Program Files (x86)\MyApp\
Remove folder: C:\Users\jackn\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\MyApp\
Completed

"MyApp"

>!define REGUINSTKEY "{ce9c1ec4-7410-4376-bf7e-4abf0bd9f0ac}" ; guidgen.com
>!include x64.nsh
OutFile "Setup_${APPNAME}.exe"
>Name "${APPNAME}"
>InstallDir "$PROGRAMFILES\${APPNAME}"
>DirText "Please choose install directory"

>Section "Install"
>SetOutPath $InstDir
File${APPNAME}.ico
File dist
${APPNAME}.jar
CreateDirectory "$InstDir\lib"
>File /oname=libjcommon-1.0.16.jar distlibjcommon-1.0.16.jar
File/oname=libjfreechart-1.0.13.jar distlibjfreechart-1.0.13.jar
File/oname=libSerialio.jar distlibSerialio.jar
WriteUninstaller $InstDirUninstall.exe
>; Check OS for proper jspWin.dll
>${If} ${RunningX64}
File /oname=$SYSDIRjspWin.dll dll64bjspWin.dll
>${Else}
File /oname=$SYSDIRjspWin.dll dll32bjspWin.dll
>${EndIf}
;Check for Java Runtime Environment (JRE)
${If} ${RunningX64}
${DisableX64FSRedirection}
${Unless} ${FileExists} "$SYSDIR\javaw.exe"
ExecWait '"jre-6u22-windows-x64.exe"'
${EndUnless}
${EnableX64FSRedirection}
${Else}
${Unless} ${FileExists} "$SYSDIR\javaw.exe"
ExecWait '"jre-6u22-windows-i586-s.exe"'
${EndUnless}
${EndIf}
>WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${REGUINSTKEY}" "UninstallString" '"$InstDir\Uninstall.exe"'
>WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${REGUINSTKEY}" "DisplayName" "${APPNAME} (remove only)"
>CreateDirectory "$SMPrograms\${APPNAME}"
>CreateShortCut "$SMPrograms\${APPNAME}\${APPNAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${APPNAME}.jar" "$InstDir\${APPNAME}.ico"
>CreateShortCut "$SMPrograms\${APPNAME}\Uninstall ${APPNAME}.lnk" "$InstDir\Uninstall.exe" "$InstDir\${APPNAME}.ico"
>MessageBox MB_OK "Installation was successful."
>SectionEnd

Section Uninstall
>${If} $InstDir != ""
Delete "$InstDir\${APPNAME}.ico"
Delete "$InstDir\${APPNAME}.jar"
Delete "$InstDir\Uninstall.exe"
RMDir /r "$InstDir\lib"
RMDir "$InstDir"
>${EndIf}
>Delete "$SMPrograms\${APPNAME}\${APPNAME}.lnk"
>Delete "$SMPrograms\${APPNAME}\Uninstall ${APPNAME}.lnk"
>RMDir "$SMPrograms\${APPNAME}"
>DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${REGUINSTKEY}"
>SectionEnd
>

Solved: also needed


RequestExecutionLevel highest 

>

Originally posted by JackN
Solved: also needed

RequestExecutionLevel highest 

>
This issue is a known NT6 problem, see http://nsis.sourceforge.net/Shortcut..._Windows_Vista (Basically, MS broke all old nsis installers)

Using "RequestExecutionLevel highest" is not the correct solution for you since you are installing stuff in $sysdir. Like I said, only admins can do that. Take a look at http://www.nsis.pastebin.com/63tS3AS2 for info on how to make sure your installer runs as admin. Also, it is probably a good idea for you to set "SetShellVarContext all" in BOTH the installer and uninstaller before touching the $smprograms variable.