Archive: Install .Net if it is not installed - newbie needs help - 99% working just one thing!


Install .Net if it is not installed - newbie needs help - 99% working just one thing!
I've installed this script http://nsis.sourceforge.net/How_to_A...eady_installed and it integrates into my installer perfectly.

If .Net isnt installed it downloads and installs it with no issues.

However - it always wants to install .Net 2.0 even if its already installed. I cant help thinking i'm doing something wrong! All i've done is copy and paste the code and change the .Net version from 1.1 to 2.0

; Usage
; 1 Call SetupDotNetSectionIfNeeded from .onInit function
; This function will check if the required version
; or higher version of the .NETFramework is installed.
; If .NET is NOT installed the section which installs dotnetfx is selected.
; If .NET is installed the section which installs dotnetfx is unselected.

#!define SF_USELECTED 0
#!define SF_SELECTED 1
#!define SF_SECGRP 2
#!define SF_BOLD 8
#!define SF_RO 16
#!define SF_EXPAND 32
###############################

!define DOT_MAJOR 2
!define DOT_MINOR 0

!macro SecSelect SecId
Push $0
IntOp $0 ${SF_SELECTED} | ${SF_RO}
SectionSetFlags ${SecId} $0
SectionSetInstTypes ${SecId} 1
Pop $0
!macroend

!define SelectSection '!insertmacro SecSelect'
#################################

!macro SecUnSelect SecId
Push $0
IntOp $0 ${SF_USELECTED} | ${SF_RO}
SectionSetFlags ${SecId} $0
SectionSetText ${SecId} ""
Pop $0
!macroend

!define UnSelectSection '!insertmacro SecUnSelect'
###################################

!macro SecExtract SecId
Push $0
IntOp $0 ${SF_USELECTED} | ${SF_RO}
SectionSetFlags ${SecId} $0
SectionSetInstTypes ${SecId} 2
Pop $0
!macroend

!define SetSectionExtract '!insertmacro SecExtract'
###################################

!macro Groups GroupId
Push $0
SectionGetFlags ${GroupId} $0
IntOp $0 $0 | ${SF_RO}
IntOp $0 $0 ^ ${SF_BOLD}
IntOp $0 $0 ^ ${SF_EXPAND}
SectionSetFlags ${GroupId} $0
Pop $0
!macroend

!define SetSectionGroup "!insertmacro Groups"
####################################

!macro GroupRO GroupId
Push $0
IntOp $0 ${SF_SECGRP} | ${SF_RO}
SectionSetFlags ${GroupId} $0
Pop $0
!macroend

!define MakeGroupReadOnly '!insertmacro GroupRO'

Function SetupDotNetSectionIfNeeded

StrCpy $0 "0"
StrCpy $1 "SOFTWARE\Microsoft\.NETFramework" ;registry entry to look in.
StrCpy $2 0

StartEnum:
;Enumerate the versions installed.
EnumRegKey $3 HKLM "$1\policy" $2

;If we don't find any versions installed, it's not here.
StrCmp $3 "" noDotNet notEmpty

;We found something.
notEmpty:
;Find out if the RegKey starts with 'v'.
;If it doesn't, goto the next key.
StrCpy $4 $3 1 0
StrCmp $4 "v" +1 goNext
StrCpy $4 $3 1 1

;It starts with 'v'. Now check to see how the installed major version
;relates to our required major version.
;If it's equal check the minor version, if it's greater,
;we found a good RegKey.
IntCmp $4 ${DOT_MAJOR} +1 goNext yesDotNetReg
;Check the minor version. If it's equal or greater to our requested
;version then we're good.
StrCpy $4 $3 1 3
IntCmp $4 ${DOT_MINOR} yesDotNetReg goNext yesDotNetReg

goNext:
;Go to the next RegKey.
IntOp $2 $2 + 1
goto StartEnum

yesDotNetReg:
;Now that we've found a good RegKey, let's make sure it's actually
;installed by getting the install path and checking to see if the
;mscorlib.dll exists.
EnumRegValue $2 HKLM "$1\policy\$3" 0
;$2 should equal whatever comes after the major and minor versions
;(ie, v1.1.4322)
StrCmp $2 "" noDotNet
ReadRegStr $4 HKLM $1 "InstallRoot"
;Hopefully the install root isn't empty.
StrCmp $4 "" noDotNet
;build the actuall directory path to mscorlib.dll.
StrCpy $4 "$4$3.$2\mscorlib.dll"
IfFileExists $4 yesDotNet noDotNet

noDotNet:
${SelectSection} ${SECDOTNET}
goto done

yesDotNet:
;Everything checks out. Go on with the rest of the installation.
${UnSelectSection} ${SECDOTNET}
goto done

done:
;All done.

FunctionEnd

!define BASE_URL http://download.microsoft.com/download
; .NET Framework
; English
!define URL_DOTNET_1033 "${BASE_URL}/5/6/7/567758a3-759e-473e-bf8f-52154438565a/dotnetfx.exe"



Var "LANGUAGE_DLL_TITLE"
Var "LANGUAGE_DLL_INFO"
Var "URL_DOTNET"
Var "OSLANGUAGE"
Var "DOTNET_RETURN_CODE"


LangString DESC_REMAINING ${LANG_ENGLISH} " (%d %s%s remaining)"
LangString DESC_PROGRESS ${LANG_ENGLISH} "%d.%01dkB/s" ;"%dkB (%d%%) of %dkB @ %d.%01dkB/s"
LangString DESC_PLURAL ${LANG_ENGLISH} "s"
LangString DESC_HOUR ${LANG_ENGLISH} "hour"
LangString DESC_MINUTE ${LANG_ENGLISH} "minute"
LangString DESC_SECOND ${LANG_ENGLISH} "second"
LangString DESC_CONNECTING ${LANG_ENGLISH} "Connecting..."
LangString DESC_DOWNLOADING ${LANG_ENGLISH} "Downloading %s"
LangString DESC_SHORTDOTNET ${LANG_ENGLISH} "Microsoft .Net Framework 2.0"
LangString DESC_LONGDOTNET ${LANG_ENGLISH} "Microsoft .Net Framework 2.0"
LangString DESC_DOTNET_DECISION ${LANG_ENGLISH} "$(DESC_SHORTDOTNET) is required.$\nIt is strongly \
advised that you install$\n$(DESC_SHORTDOTNET) before continuing.$\nIf you choose to continue, \
you will need to connect$\nto the internet before proceeding.$\nWould you like to continue with \
the installation?"
LangString SEC_DOTNET ${LANG_ENGLISH} "$(DESC_SHORTDOTNET) "
LangString DESC_INSTALLING ${LANG_ENGLISH} "Installing"
LangString DESC_DOWNLOADING1 ${LANG_ENGLISH} "Downloading"
LangString DESC_DOWNLOADFAILED ${LANG_ENGLISH} "Download Failed:"
LangString ERROR_DOTNET_DUPLICATE_INSTANCE ${LANG_ENGLISH} "The $(DESC_SHORTDOTNET) Installer is \
already running."
LangString ERROR_NOT_ADMINISTRATOR ${LANG_ENGLISH} "$(DESC_000022)"
LangString ERROR_INVALID_PLATFORM ${LANG_ENGLISH} "$(DESC_000023)"
LangString DESC_DOTNET_TIMEOUT ${LANG_ENGLISH} "The installation of the $(DESC_SHORTDOTNET) \
has timed out."
LangString ERROR_DOTNET_INVALID_PATH ${LANG_ENGLISH} "The $(DESC_SHORTDOTNET) Installation$\n\
was not found in the following location:$\n"
LangString ERROR_DOTNET_FATAL ${LANG_ENGLISH} "A fatal error occurred during the installation$\n\
of the $(DESC_SHORTDOTNET)."
LangString FAILED_DOTNET_INSTALL ${LANG_ENGLISH} "The installation of $(PRODUCT_NAME) will$\n\
continue. However, it may not function properly$\nuntil $(DESC_SHORTDOTNET)$\nis installed."


Section $(SEC_DOTNET) SECDOTNET
SectionIn RO
IfSilent lbl_IsSilent
!define DOTNETFILESDIR "Common\Files\MSNET"
StrCpy $DOTNET_RETURN_CODE "0"
!ifdef DOTNET_ONCD_1033
StrCmp "$OSLANGUAGE" "1033" 0 lbl_Not1033
SetOutPath "$PLUGINSDIR"
file /r "${DOTNETFILESDIR}\dotnetfx1033.exe"
DetailPrint "$(DESC_INSTALLING) $(DESC_SHORTDOTNET)..."
Banner::show /NOUNLOAD "$(DESC_INSTALLING) $(DESC_SHORTDOTNET)..."
nsExec::ExecToStack '"$PLUGINSDIR\dotnetfx1033.exe" /q /c:"install.exe /noaspupgrade /q"'
pop $DOTNET_RETURN_CODE
Banner::destroy
SetRebootFlag true
Goto lbl_NoDownloadRequired
lbl_Not1033:
!endif
; Insert Other language blocks here

; the following Goto and Label is for consistencey.
Goto lbl_DownloadRequired
lbl_DownloadRequired:
DetailPrint "$(DESC_DOWNLOADING1) $(DESC_SHORTDOTNET)..."
MessageBox MB_ICONEXCLAMATION|MB_YESNO|MB_DEFBUTTON2 "$(DESC_DOTNET_DECISION)" /SD IDNO \
IDYES +2 IDNO 0
Abort
; "Downloading Microsoft .Net Framework"
AddSize 153600
nsisdl::download /TRANSLATE "$(DESC_DOWNLOADING)" "$(DESC_CONNECTING)" \
"$(DESC_SECOND)" "$(DESC_MINUTE)" "$(DESC_HOUR)" "$(DESC_PLURAL)" \
"$(DESC_PROGRESS)" "$(DESC_REMAINING)" \
/TIMEOUT=30000 "$URL_DOTNET" "$PLUGINSDIR\dotnetfx.exe"
Pop $0
StrCmp "$0" "success" lbl_continue
DetailPrint "$(DESC_DOWNLOADFAILED) $0"
Abort

lbl_continue:
DetailPrint "$(DESC_INSTALLING) $(DESC_SHORTDOTNET)..."
Banner::show /NOUNLOAD "$(DESC_INSTALLING) $(DESC_SHORTDOTNET)..."
nsExec::ExecToStack '"$PLUGINSDIR\dotnetfx.exe" /q /c:"install.exe /noaspupgrade /q"'
pop $DOTNET_RETURN_CODE
Banner::destroy
SetRebootFlag true
; silence the compiler
Goto lbl_NoDownloadRequired
lbl_NoDownloadRequired:

; obtain any error code and inform the user ($DOTNET_RETURN_CODE)
; If nsExec is unable to execute the process,
; it will return "error"
; If the process timed out it will return "timeout"
; else it will return the return code from the executed process.
StrCmp "$DOTNET_RETURN_CODE" "" lbl_NoError
StrCmp "$DOTNET_RETURN_CODE" "0" lbl_NoError
StrCmp "$DOTNET_RETURN_CODE" "3010" lbl_NoError
StrCmp "$DOTNET_RETURN_CODE" "8192" lbl_NoError
StrCmp "$DOTNET_RETURN_CODE" "error" lbl_Error
StrCmp "$DOTNET_RETURN_CODE" "timeout" lbl_TimeOut
; It's a .Net Error
StrCmp "$DOTNET_RETURN_CODE" "4101" lbl_Error_DuplicateInstance
StrCmp "$DOTNET_RETURN_CODE" "4097" lbl_Error_NotAdministrator
StrCmp "$DOTNET_RETURN_CODE" "1633" lbl_Error_InvalidPlatform lbl_FatalError
; all others are fatal

lbl_Error_DuplicateInstance:
DetailPrint "$(ERROR_DOTNET_DUPLICATE_INSTANCE)"
GoTo lbl_Done

lbl_Error_NotAdministrator:
DetailPrint "$(ERROR_NOT_ADMINISTRATOR)"
GoTo lbl_Done

lbl_Error_InvalidPlatform:
DetailPrint "$(ERROR_INVALID_PLATFORM)"
GoTo lbl_Done

lbl_TimeOut:
DetailPrint "$(DESC_DOTNET_TIMEOUT)"
GoTo lbl_Done

lbl_Error:
DetailPrint "$(ERROR_DOTNET_INVALID_PATH)"
GoTo lbl_Done

lbl_FatalError:
DetailPrint "$(ERROR_DOTNET_FATAL)[$DOTNET_RETURN_CODE]"
GoTo lbl_Done

lbl_Done:
DetailPrint "$(FAILED_DOTNET_INSTALL)"
lbl_NoError:
lbl_IsSilent:
SectionEnd

!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SECDOTNET} $(DESC_LONGDOTNET)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
and then i'm pasting this at the bottom of my .nsi compiler file

Function .onInit
StrCpy $LANGUAGE_DLL_TITLE "Installer Language"
StrCpy $LANGUAGE_DLL_INFO "Please select a language:"
StrCpy $URL_DOTNET "${URL_DOTNET_1033}"
StrCpy $OSLANGUAGE "1033"

; Insert other Language Blocks Here

!define MUI_LANGDLL_WINDOWTITLE "$LANGUAGE_DLL_TITLE"
!define MUI_LANGDLL_INFO "$LANGUAGE_DLL_INFO"
!insertmacro MUI_LANGDLL_DISPLAY
!undef MUI_LANGDLL_WINDOWTITLE
!undef MUI_LANGDLL_INFO
InitPluginsDir
SetOutPath "$PLUGINSDIR"
File /r "${NSISDIR}\Plugins\*.*"
FunctionEnd

Looks like that code is written to only work with .NET 1.1. 2.0 and above do not depend on 1.1 and therefore the check is not going to work. In particular, the HKLM\Software\Microsoft\.NETFramework\Policy key it is enumerating does not contain any .NET version information after 1.1. You need to be enumerating the HKLM\Software\Microsoft\NET Framework Setup\NDP key instead.

Stu


Thanks Stu - i'll look at the keys in more detail - thought i was installing it wrong!