DotNET: Difference between revisions
From NSIS Wiki
Jump to navigationJump to search
(false positive virus warning) |
|||
(8 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
== Overview == | == Overview == | ||
DotNET is a macro written to aid in the deployment of .NET Framework 2.0-based applications using NSIS. | DotNET is a macro written to aid in the deployment of .NET Framework 2.0-based applications using NSIS. | ||
Line 9: | Line 8: | ||
=== Limitations === | === Limitations === | ||
* Only works for .NET Framework | * Only works for .NET Framework 3.5, not 1.0 or 1.1 or 2.5 or 3.0 ... | ||
* See talk page for 3.5 hack up! | |||
* Won't work on XP 64 (as downloads the 32 bit installer by default) | |||
* High risk of causing a false positive for "generic downloader trojan" in Kasperky antivirus software. No matter if you use inetc or NSISDL (verified in production with 1000+ downloads 2011-09-09). | |||
== Usage == | == Usage == | ||
Line 42: | Line 44: | ||
<div style="overflow: auto; width=100%;"> | <div style="overflow: auto; width=100%;"> | ||
<highlight-nsis> | <highlight-nsis> | ||
# DotNET version checking macro. | # DotNET and MSI version checking macro. | ||
# Written by AnarkiNet(AnarkiNet@gmail.com) originally | # Written by AnarkiNet(AnarkiNet@gmail.com) originally | ||
# | # modified by eyal0 in 2007 and sevenalive in 2010 | ||
# Installs the Microsoft .NET Framework version 3.5 SP1 if the required .NET runtime is not installed | |||
# To use, call the macro with a string: | # To use, call the macro with a string: | ||
# !insertmacro CheckDotNET | # Example: non real version numbers | ||
# !insertmacro CheckDotNET | # !insertmacro CheckDotNET 3.5 | ||
# !insertmacro CheckDotNET 3.5sp1 | |||
# (Version 2.0.9 is less than version 2.0.10.) | # (Version 2.0.9 is less than version 2.0.10.) | ||
# Example: latest real version number at time of writing | |||
# !insertmacro CheckDotNET "2.0.50727" | |||
# All register variables are saved and restored by CheckDotNet | # All register variables are saved and restored by CheckDotNet | ||
# No output | # No output | ||
Var DN3Dir | |||
Var dotnet3 ; is .NET 3 installed? | |||
Var dotnet35 ; is .NET 3.5 installed? | |||
Var dotnet35ver ; 3.5 version | |||
Var dotnet35sp1 ; sp1 | |||
!macro CheckDotNET DotNetReqVer | !macro CheckDotNET DotNetReqVer | ||
!define DOTNET_URL "http:// | !define DOTNET_URL "http://download.microsoft.com/download/2/0/e/20e90413-712f-438c-988e-fdaa79a8ac3d/dotnetfx35.exe" | ||
DetailPrint "Checking your .NET Framework version..." | DetailPrint "Checking your .NET Framework version..." | ||
Push $0 | Push $0 | ||
Push $1 | Push $1 | ||
Line 64: | Line 73: | ||
Push $6 ;backup of intsalled ver | Push $6 ;backup of intsalled ver | ||
Push $7 ;backup of DoNetReqVer | Push $7 ;backup of DoNetReqVer | ||
# NSIS | |||
ReadRegStr $dotnet3 HKEY_LOCAL_MACHINE "Software\Microsoft\NET Framework Setup\NDP\v3.0\Setup" "InstallSuccess" | |||
ReadRegStr $dotnet35 HKEY_LOCAL_MACHINE "Software\Microsoft\NET Framework Setup\NDP\v3.5" "Install" | |||
ReadRegStr $dotnet35ver HKEY_LOCAL_MACHINE "Software\Microsoft\NET Framework Setup\NDP\v3.5" "Version" | |||
ReadRegStr $dotnet35sp1 HKEY_LOCAL_MACHINE "Software\Microsoft\NET Framework Setup\NDP\v3.5" "SP" | |||
StrCpy $7 ${DotNetReqVer} | StrCpy $7 ${DotNetReqVer} | ||
System::Call "mscoree::GetCORVersion(w .r0, i ${NSIS_MAX_STRLEN}, *i r2r2) i .r1 ?u" | System::Call "mscoree::GetCORVersion(w .r0, i ${NSIS_MAX_STRLEN}, *i r2r2) i .r1 ?u" | ||
DetailPrint ".NET Framework Version $0 found" | |||
${If} $0 == 0 | ${If} $0 == 0 | ||
DetailPrint ".NET Framework not found, download is required for program to run." | DetailPrint ".NET Framework not found, download is required for program to run." | ||
Goto NoDotNET | Goto NoDotNET | ||
${EndIf} | ${EndIf} | ||
${If} $0 == "" | |||
DetailPrint ".NET Framework not found, download is required for program to run." | |||
Goto NoDotNET | |||
${EndIf} | |||
;at this point, $0 has maybe v2.345.678. | ;at this point, $0 has maybe v2.345.678. | ||
StrCpy $0 $0 $2 1 ;remove the starting "v", $0 has the installed version num as a string | StrCpy $0 $0 $2 1 ;remove the starting "v", $0 has the installed version num as a string | ||
StrCpy $6 $0 | StrCpy $6 $0 | ||
StrCpy $1 $7 ;$1 has the requested verison num as a string | StrCpy $1 $7 ;$1 has the requested verison num as a string | ||
;now let's compare the versions, installed against required <part0>.<part1>.<part2>. | ;now let's compare the versions, installed against required <part0>.<part1>.<part2>. | ||
${Do} | ${Do} | ||
StrCpy $2 "" ;clear out the installed part | StrCpy $2 "" ;clear out the installed part | ||
StrCpy $3 "" ;clear out the required part | StrCpy $3 "" ;clear out the required part | ||
${Do} | ${Do} | ||
${If} $0 == "" ;if there are no more characters in the version | ${If} $0 == "" ;if there are no more characters in the version | ||
Line 97: | Line 112: | ||
${EndIf} | ${EndIf} | ||
${EndIf} | ${EndIf} | ||
${If} $1 == "" ;if there are no more characters in the version | ${If} $1 == "" ;if there are no more characters in the version | ||
StrCpy $5 "." ;fake the end of the version string | StrCpy $5 "." ;fake the end of the version string | ||
Line 106: | Line 121: | ||
${EndIf} | ${EndIf} | ||
${EndIf} | ${EndIf} | ||
${If} $4 == "." | ${If} $4 == "." | ||
${AndIf} $5 == "." | ${AndIf} $5 == "." | ||
${ExitDo} ;we're at the end of the part | ${ExitDo} ;we're at the end of the part | ||
${EndIf} | ${EndIf} | ||
${If} $4 == "." ;if we're at the end of the current installed part | ${If} $4 == "." ;if we're at the end of the current installed part | ||
StrCpy $2 "0$2" ;put a zero on the front | StrCpy $2 "0$2" ;put a zero on the front | ||
Line 123: | Line 137: | ||
${EndIf} | ${EndIf} | ||
${Loop} | ${Loop} | ||
${If} $0 != "" ;let's remove the leading period on installed part if it exists | ${If} $0 != "" ;let's remove the leading period on installed part if it exists | ||
StrCpy $0 $0 ${NSIS_MAX_STRLEN} 1 | StrCpy $0 $0 ${NSIS_MAX_STRLEN} 1 | ||
Line 131: | Line 144: | ||
StrCpy $1 $1 ${NSIS_MAX_STRLEN} 1 | StrCpy $1 $1 ${NSIS_MAX_STRLEN} 1 | ||
${EndIf} | ${EndIf} | ||
;$2 has the installed part, $3 has the required part | ;$2 has the installed part, $3 has the required part | ||
${If} $2 S< $3 | ${If} $2 S< $3 | ||
Line 145: | Line 158: | ||
${EndIf} ;otherwise we just keep looping through the parts | ${EndIf} ;otherwise we just keep looping through the parts | ||
${Loop} | ${Loop} | ||
;check to see if v3 and/or v3.5 is installed | |||
${If} $0 < 0 | ${If} $0 < 0 | ||
${If} $dotnet3 == "1" | |||
DetailPrint ".NET Framework Version 3 found" | |||
${If} $dotnet35 == "1" | |||
DetailPrint ".NET Framework Version 3.5 found" | |||
${If} $dotnet35sp1 != "1" | |||
DetailPrint "SP1 needed. Installing..." | |||
Goto DownloadDotNET | |||
${EndIf} | |||
DetailPrint ".NET Framework Version 3.5 SP1 found" | |||
Goto NewDotNET | |||
${EndIf} | |||
${EndIf} | |||
DetailPrint ".NET Framework Version found: $6, but is older than the required version: $7" | DetailPrint ".NET Framework Version found: $6, but is older than the required version: $7" | ||
Goto OldDotNET | Goto OldDotNET | ||
Line 153: | Line 180: | ||
Goto NewDotNET | Goto NewDotNET | ||
${EndIf} | ${EndIf} | ||
NoDotNET: | NoDotNET: | ||
goto DownloadDotNET | |||
OldDotNET: | OldDotNET: | ||
ReadRegStr $DN3Dir HKLM "SOFTWARE\Microsoft\.NETFramework" "InstallRoot" | |||
" | StrCpy $DN3Dir "$DN3Dir\v3.5\csc.exe" | ||
goto | IfFileExists $DN3Dir NewDotNET | ||
goto DownloadDotNET | |||
DownloadDotNET: | DownloadDotNET: | ||
DetailPrint "Beginning download of latest .NET Framework version." | DetailPrint "Beginning download of latest .NET Framework version." | ||
inetc::get /TIMEOUT=30000 ${DOTNET_URL} "$TEMP\dotnetfx35.exe" /END | |||
Pop $0 | |||
DetailPrint "Result: $0" | |||
StrCmp $0 "OK" InstallDotNet | |||
StrCmp $0 "cancelled" GiveUpDotNET | |||
inetc::get /TIMEOUT=30000 /NOPROXY ${DOTNET_URL} "$TEMP\dotnetfx35.exe" /END | |||
Pop $0 | |||
DetailPrint "Result: $0" | |||
StrCmp $0 "OK" InstallDotNet | |||
MessageBox MB_ICONSTOP "Download failed: $0" | |||
Abort | |||
InstallDotNet: | |||
DetailPrint "Completed download." | DetailPrint "Completed download." | ||
Pop $0 | Pop $0 | ||
Line 173: | Line 210: | ||
MessageBox MB_YESNO|MB_ICONEXCLAMATION \ | MessageBox MB_YESNO|MB_ICONEXCLAMATION \ | ||
"Download cancelled. Continue Installation?" \ | "Download cancelled. Continue Installation?" \ | ||
IDYES NewDotNET IDNO GiveUpDotNET | IDYES NewDotNET IDNO GiveUpDotNET | ||
${EndIf} | ${EndIf} | ||
; TryFailedDownload: | |||
DetailPrint "Pausing installation while downloaded .NET Framework installer runs." | DetailPrint "Pausing installation while downloaded .NET Framework installer runs." | ||
ExecWait '$TEMP\ | ExecWait '$TEMP\dotnetfx35.exe /q /norestart /c:"install /q"' | ||
DetailPrint "Completed .NET Framework install/update. Removing .NET Framework installer." | DetailPrint "Completed .NET Framework install/update. Removing .NET Framework installer." | ||
Delete "$TEMP\ | Delete "$TEMP\dotnetfx35.exe" | ||
DetailPrint ".NET Framework installer removed." | DetailPrint ".NET Framework installer removed." | ||
goto NewDotNet | goto NewDotNet | ||
GiveUpDotNET: | GiveUpDotNET: | ||
Abort "Installation cancelled by user." | Abort "Installation cancelled by user." | ||
NewDotNET: | NewDotNET: | ||
Pop $7 | |||
Pop $6 | |||
Pop $5 | |||
Pop $4 | |||
Pop $3 | |||
Pop $2 | |||
Pop $1 | |||
Pop $0 | Pop $0 | ||
!macroend | !macroend | ||
</highlight-nsis></div> | </highlight-nsis></div> | ||
[[Special:Contributions/97.117.134.8|97.117.134.8]] 22:20, 28 February 2010 (UTC) | |||
== MSI Check Overview == | == MSI Check Overview == | ||
Line 428: | Line 461: | ||
NewDotNET: | NewDotNET: | ||
DetailPrint "Proceeding with remainder of installation." | DetailPrint "Proceeding with remainder of installation." | ||
Pop $7 | |||
Pop $6 | |||
Pop $5 | |||
Pop $4 | |||
Pop $3 | |||
Pop $2 | |||
Pop $1 | |||
Pop $0 | Pop $0 | ||
!macroend | !macroend | ||
</highlight-nsis></div> | </highlight-nsis></div> |
Latest revision as of 12:22, 9 September 2011
Overview
DotNET is a macro written to aid in the deployment of .NET Framework 2.0-based applications using NSIS.
What it does
- Checks the version of the .NET framework on the end-user's computer.
- Prompts them with a yes/no dialog if their version is different than the defined DOTNET_VERSION in the installer's main script.
- If they press yes, the installer downloads the latest .NET Framework 2.0 installer and runs it.
Limitations
- Only works for .NET Framework 3.5, not 1.0 or 1.1 or 2.5 or 3.0 ...
- See talk page for 3.5 hack up!
- Won't work on XP 64 (as downloads the 32 bit installer by default)
- High risk of causing a false positive for "generic downloader trojan" in Kasperky antivirus software. No matter if you use inetc or NSISDL (verified in production with 1000+ downloads 2011-09-09).
Usage
Including the Script
Save the Script contents as DotNET.nsh in the same folder as your main script, and put line in your main script like this:
!include "DotNET.nsh"
DotNet.nsh uses the ${if} function of LogicLib, so you also have to include it in your script:
!include LogicLib.nsh
Required Variables
Define the variable DOTNET_VERSION as the full or partial version of .NET Framework your app requires, like so:
!define DOTNET_VERSION "2.0.50727"
or
!define DOTNET_VERSION "2.0.5"
or
!define DOTNET_VERSION "2"
Using the Script
Insert the macro CheckDotNET into your script inside the first required section of the installer:
Section "Main Section (Required)" SectionIn RO !insertmacro CheckDotNET ${DOTNET_VERSION} #Files here SectionEnd
The Script
# DotNET and MSI version checking macro. # Written by AnarkiNet(AnarkiNet@gmail.com) originally # modified by eyal0 in 2007 and sevenalive in 2010 # Installs the Microsoft .NET Framework version 3.5 SP1 if the required .NET runtime is not installed # To use, call the macro with a string: # Example: non real version numbers # !insertmacro CheckDotNET 3.5 # !insertmacro CheckDotNET 3.5sp1 # (Version 2.0.9 is less than version 2.0.10.) # Example: latest real version number at time of writing # !insertmacro CheckDotNET "2.0.50727" # All register variables are saved and restored by CheckDotNet # No output Var DN3Dir Var dotnet3 ; is .NET 3 installed? Var dotnet35 ; is .NET 3.5 installed? Var dotnet35ver ; 3.5 version Var dotnet35sp1 ; sp1 !macro CheckDotNET DotNetReqVer !define DOTNET_URL "http://download.microsoft.com/download/2/0/e/20e90413-712f-438c-988e-fdaa79a8ac3d/dotnetfx35.exe" DetailPrint "Checking your .NET Framework version..." Push $0 Push $1 Push $2 Push $3 Push $4 Push $5 Push $6 ;backup of intsalled ver Push $7 ;backup of DoNetReqVer # NSIS ReadRegStr $dotnet3 HKEY_LOCAL_MACHINE "Software\Microsoft\NET Framework Setup\NDP\v3.0\Setup" "InstallSuccess" ReadRegStr $dotnet35 HKEY_LOCAL_MACHINE "Software\Microsoft\NET Framework Setup\NDP\v3.5" "Install" ReadRegStr $dotnet35ver HKEY_LOCAL_MACHINE "Software\Microsoft\NET Framework Setup\NDP\v3.5" "Version" ReadRegStr $dotnet35sp1 HKEY_LOCAL_MACHINE "Software\Microsoft\NET Framework Setup\NDP\v3.5" "SP" StrCpy $7 ${DotNetReqVer} System::Call "mscoree::GetCORVersion(w .r0, i ${NSIS_MAX_STRLEN}, *i r2r2) i .r1 ?u" DetailPrint ".NET Framework Version $0 found" ${If} $0 == 0 DetailPrint ".NET Framework not found, download is required for program to run." Goto NoDotNET ${EndIf} ${If} $0 == "" DetailPrint ".NET Framework not found, download is required for program to run." Goto NoDotNET ${EndIf} ;at this point, $0 has maybe v2.345.678. StrCpy $0 $0 $2 1 ;remove the starting "v", $0 has the installed version num as a string StrCpy $6 $0 StrCpy $1 $7 ;$1 has the requested verison num as a string ;now let's compare the versions, installed against required <part0>.<part1>.<part2>. ${Do} StrCpy $2 "" ;clear out the installed part StrCpy $3 "" ;clear out the required part ${Do} ${If} $0 == "" ;if there are no more characters in the version StrCpy $4 "." ;fake the end of the version string ${Else} StrCpy $4 $0 1 0 ;$4 = character from the installed ver ${If} $4 != "." StrCpy $0 $0 ${NSIS_MAX_STRLEN} 1 ;remove that first character from the remaining ${EndIf} ${EndIf} ${If} $1 == "" ;if there are no more characters in the version StrCpy $5 "." ;fake the end of the version string ${Else} StrCpy $5 $1 1 0 ;$5 = character from the required ver ${If} $5 != "." StrCpy $1 $1 ${NSIS_MAX_STRLEN} 1 ;remove that first character from the remaining ${EndIf} ${EndIf} ${If} $4 == "." ${AndIf} $5 == "." ${ExitDo} ;we're at the end of the part ${EndIf} ${If} $4 == "." ;if we're at the end of the current installed part StrCpy $2 "0$2" ;put a zero on the front ${Else} ;we have another character StrCpy $2 "$2$4" ;put the next character on the back ${EndIf} ${If} $5 == "." ;if we're at the end of the current required part StrCpy $3 "0$3" ;put a zero on the front ${Else} ;we have another character StrCpy $3 "$3$5" ;put the next character on the back ${EndIf} ${Loop} ${If} $0 != "" ;let's remove the leading period on installed part if it exists StrCpy $0 $0 ${NSIS_MAX_STRLEN} 1 ${EndIf} ${If} $1 != "" ;let's remove the leading period on required part if it exists StrCpy $1 $1 ${NSIS_MAX_STRLEN} 1 ${EndIf} ;$2 has the installed part, $3 has the required part ${If} $2 S< $3 IntOp $0 0 - 1 ;$0 = -1, installed less than required ${ExitDo} ${ElseIf} $2 S> $3 IntOp $0 0 + 1 ;$0 = 1, installed greater than required ${ExitDo} ${ElseIf} $2 == "" ${AndIf} $3 == "" IntOp $0 0 + 0 ;$0 = 0, the versions are identical ${ExitDo} ${EndIf} ;otherwise we just keep looping through the parts ${Loop} ;check to see if v3 and/or v3.5 is installed ${If} $0 < 0 ${If} $dotnet3 == "1" DetailPrint ".NET Framework Version 3 found" ${If} $dotnet35 == "1" DetailPrint ".NET Framework Version 3.5 found" ${If} $dotnet35sp1 != "1" DetailPrint "SP1 needed. Installing..." Goto DownloadDotNET ${EndIf} DetailPrint ".NET Framework Version 3.5 SP1 found" Goto NewDotNET ${EndIf} ${EndIf} DetailPrint ".NET Framework Version found: $6, but is older than the required version: $7" Goto OldDotNET ${Else} DetailPrint ".NET Framework Version found: $6, equal or newer to required version: $7." Goto NewDotNET ${EndIf} NoDotNET: goto DownloadDotNET OldDotNET: ReadRegStr $DN3Dir HKLM "SOFTWARE\Microsoft\.NETFramework" "InstallRoot" StrCpy $DN3Dir "$DN3Dir\v3.5\csc.exe" IfFileExists $DN3Dir NewDotNET goto DownloadDotNET DownloadDotNET: DetailPrint "Beginning download of latest .NET Framework version." inetc::get /TIMEOUT=30000 ${DOTNET_URL} "$TEMP\dotnetfx35.exe" /END Pop $0 DetailPrint "Result: $0" StrCmp $0 "OK" InstallDotNet StrCmp $0 "cancelled" GiveUpDotNET inetc::get /TIMEOUT=30000 /NOPROXY ${DOTNET_URL} "$TEMP\dotnetfx35.exe" /END Pop $0 DetailPrint "Result: $0" StrCmp $0 "OK" InstallDotNet MessageBox MB_ICONSTOP "Download failed: $0" Abort InstallDotNet: DetailPrint "Completed download." Pop $0 ${If} $0 == "cancel" MessageBox MB_YESNO|MB_ICONEXCLAMATION \ "Download cancelled. Continue Installation?" \ IDYES NewDotNET IDNO GiveUpDotNET ${EndIf} ; TryFailedDownload: DetailPrint "Pausing installation while downloaded .NET Framework installer runs." ExecWait '$TEMP\dotnetfx35.exe /q /norestart /c:"install /q"' DetailPrint "Completed .NET Framework install/update. Removing .NET Framework installer." Delete "$TEMP\dotnetfx35.exe" DetailPrint ".NET Framework installer removed." goto NewDotNet GiveUpDotNET: Abort "Installation cancelled by user." NewDotNET: Pop $7 Pop $6 Pop $5 Pop $4 Pop $3 Pop $2 Pop $1 Pop $0 !macroend
97.117.134.8 22:20, 28 February 2010 (UTC)
MSI Check Overview
Added check for MSI3. MSI check code based on [1]
What it does
- Checks the version of the MSI on the end-user's computer.
- Prompts them with a yes/no dialog if their version is lower than 3.
- If they press yes, the installer downloads the latest MSI3.1 installer and runs it.
- Checks the version of the .NET framework on the end-user's computer.
- Prompts them with a yes/no dialog if their version is different than the defined DOTNET_VERSION in the installer's main script.
- If they press yes, the installer downloads the latest .NET Framework 2.0 installer and runs it.
The Script With MSI Check
# DotNET and MSI version checking macro. # Written by AnarkiNet(AnarkiNet@gmail.com) originally, modified by eyal0 (for use in http://www.sourceforge.net/projects/itwister) # MSI check code based on http://www.codeproject.com/useritems/NSIS.asp # Downloads the MSI version 3.1 and runs it if the user does not have the correct version. # Downloads and runs the Microsoft .NET Framework version 2.0 Redistributable and runs it if the user does not have the correct version. # To use, call the macro with a string: # Example: non real version numbers # !insertmacro CheckDotNET "2" # !insertmacro CheckDotNET "2.0.9" # (Version 2.0.9 is less than version 2.0.10.) # Example: latest real version number at time of writing # !insertmacro CheckDotNET "2.0.50727" # All register variables are saved and restored by CheckDotNet # No output !macro CheckDotNET DotNetReqVer !define DOTNET_URL "http://www.microsoft.com/downloads/info.aspx?na=90&p=&SrcDisplayLang=en&SrcCategoryId=&SrcFamilyId=0856eacb-4362-4b0d-8edd-aab15c5e04f5&u=http%3a%2f%2fdownload.microsoft.com%2fdownload%2f5%2f6%2f7%2f567758a3-759e-473e-bf8f-52154438565a%2fdotnetfx.exe" !define MSI31_URL "http://download.microsoft.com/download/1/4/7/147ded26-931c-4daf-9095-ec7baf996f46/WindowsInstaller-KB893803-v2-x86.exe" DetailPrint "Checking your .NET Framework version..." ;callee register save Push $0 Push $1 Push $2 Push $3 Push $4 Push $5 Push $6 ;backup of intsalled ver Push $7 ;backup of DoNetReqVer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; MSI ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GetDLLVersion "$SYSDIR\msi.dll" $R0 $R1 IntOp $R2 $R0 / 0x00010000 ; $R2 now contains major version IntOp $R3 $R0 & 0x0000FFFF ; $R3 now contains minor version IntOp $R4 $R1 / 0x00010000 ; $R4 now contains release IntOp $R5 $R1 & 0x0000FFFF ; $R5 now contains build StrCpy $0 "$R2.$R3.$R4.$R5" ; $0 now contains string like "1.2.0.192" ${If} $R2 < '3' ;options SetOutPath "$TEMP" SetOverwrite on MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION \ "Your MSI version: $0.$\nRequired Version: 3 or greater.$\nDownload MSI version from www.microsoft.com?" \ /SD IDYES IDYES DownloadMSI IDNO NewMSI goto GiveUpDotNET ;IDCANCEL ${Else} DetailPrint "MSI3.1 already installed" goto NewMSI ${EndIf} DownloadMSI: DetailPrint "Beginning download of MSI3.1." NSISDL::download ${MSI31_URL} "$TEMP\WindowsInstaller-KB893803-v2-x86.exe" DetailPrint "Completed download." Pop $0 ${If} $0 == "cancel" MessageBox MB_YESNO|MB_ICONEXCLAMATION \ "Download cancelled. Continue Installation?" \ IDYES NewMSI IDNO GiveUpDotNET ${ElseIf} $0 != "success" MessageBox MB_YESNO|MB_ICONEXCLAMATION \ "Download failed:$\n$0$\n$\nContinue Installation?" \ IDYES NewMSI IDNO GiveUpDotNET ${EndIf} DetailPrint "Pausing installation while downloaded MSI3.1 installer runs." ExecWait '$TEMP\WindowsInstaller-KB893803-v2-x86.exe /quiet /norestart' $0 DetailPrint "Completed MSI3.1 install/update. Exit code = '$0'. Removing MSI3.1 installer." Delete "$TEMP\WindowsInstaller-KB893803-v2-x86.exe" DetailPrint "MSI3.1 installer removed." goto NewMSI NewMSI: DetailPrint "MSI3.1 installation done. Proceeding with remainder of installation." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; NetFX ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; StrCpy $7 ${DotNetReqVer} System::Call "mscoree::GetCORVersion(w .r0, i ${NSIS_MAX_STRLEN}, *i r2r2) i .r1 ?u" ${If} $0 == 0 DetailPrint ".NET Framework not found, download is required for program to run." Goto NoDotNET ${EndIf} ;at this point, $0 has maybe v2.345.678. StrCpy $0 $0 $2 1 ;remove the starting "v", $0 has the installed version num as a string StrCpy $6 $0 StrCpy $1 $7 ;$1 has the requested verison num as a string ;MessageBox MB_OKCANCEL "found $0" IDCANCEL GiveUpDotNET ;MessageBox MB_OKCANCEL "looking for $1" IDCANCEL GiveUpDotNET ;now let's compare the versions, installed against required <part0>.<part1>.<part2>. ${Do} StrCpy $2 "" ;clear out the installed part StrCpy $3 "" ;clear out the required part ${Do} ${If} $0 == "" ;if there are no more characters in the version StrCpy $4 "." ;fake the end of the version string ${Else} StrCpy $4 $0 1 0 ;$4 = character from the installed ver ${If} $4 != "." StrCpy $0 $0 ${NSIS_MAX_STRLEN} 1 ;remove that first character from the remaining ${EndIf} ${EndIf} ${If} $1 == "" ;if there are no more characters in the version StrCpy $5 "." ;fake the end of the version string ${Else} StrCpy $5 $1 1 0 ;$5 = character from the required ver ${If} $5 != "." StrCpy $1 $1 ${NSIS_MAX_STRLEN} 1 ;remove that first character from the remaining ${EndIf} ${EndIf} ;MessageBox MB_OKCANCEL "installed $2,$4,$0 required $3,$5,$1" IDCANCEL GiveUpDotNET ${If} $4 == "." ${AndIf} $5 == "." ${ExitDo} ;we're at the end of the part ${EndIf} ${If} $4 == "." ;if we're at the end of the current installed part StrCpy $2 "0$2" ;put a zero on the front ${Else} ;we have another character StrCpy $2 "$2$4" ;put the next character on the back ${EndIf} ${If} $5 == "." ;if we're at the end of the current required part StrCpy $3 "0$3" ;put a zero on the front ${Else} ;we have another character StrCpy $3 "$3$5" ;put the next character on the back ${EndIf} ${Loop} ;MessageBox MB_OKCANCEL "finished parts: installed $2,$4,$0 required $3,$5,$1" IDCANCEL GiveUpDotNET ${If} $0 != "" ;let's remove the leading period on installed part if it exists StrCpy $0 $0 ${NSIS_MAX_STRLEN} 1 ${EndIf} ${If} $1 != "" ;let's remove the leading period on required part if it exists StrCpy $1 $1 ${NSIS_MAX_STRLEN} 1 ${EndIf} ;$2 has the installed part, $3 has the required part ${If} $2 S< $3 IntOp $0 0 - 1 ;$0 = -1, installed less than required ${ExitDo} ${ElseIf} $2 S> $3 IntOp $0 0 + 1 ;$0 = 1, installed greater than required ${ExitDo} ${ElseIf} $2 == "" ${AndIf} $3 == "" IntOp $0 0 + 0 ;$0 = 0, the versions are identical ${ExitDo} ${EndIf} ;otherwise we just keep looping through the parts ${Loop} ${If} $0 < 0 DetailPrint ".NET Framework Version found: $6, but is older than the required version: $7" Goto OldDotNET ${Else} DetailPrint ".NET Framework Version found: $6, equal or newer to required version: $7." Goto NewDotNET ${EndIf} NoDotNET: MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION \ ".NET Framework not installed.$\nRequired Version: $7 or greater.$\nDownload .NET Framework version from www.microsoft.com?" \ /SD IDYES IDYES DownloadDotNET IDNO NewDotNET goto GiveUpDotNET ;IDCANCEL OldDotNET: MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION \ "Your .NET Framework version: $6.$\nRequired Version: $7 or greater.$\nDownload .NET Framework version from www.microsoft.com?" \ /SD IDYES IDYES DownloadDotNET IDNO NewDotNET goto GiveUpDotNET ;IDCANCEL DownloadDotNET: DetailPrint "Beginning download of latest .NET Framework version." NSISDL::download ${DOTNET_URL} "$TEMP\dotnetfx.exe" DetailPrint "Completed download." Pop $0 ${If} $0 == "cancel" MessageBox MB_YESNO|MB_ICONEXCLAMATION \ "Download cancelled. Continue Installation?" \ IDYES NewDotNET IDNO GiveUpDotNET ${ElseIf} $0 != "success" MessageBox MB_YESNO|MB_ICONEXCLAMATION \ "Download failed:$\n$0$\n$\nContinue Installation?" \ IDYES NewDotNET IDNO GiveUpDotNET ${EndIf} DetailPrint "Pausing installation while downloaded .NET Framework installer runs." ExecWait '$TEMP\dotnetfx.exe /q /c:"install /q"' DetailPrint "Completed .NET Framework install/update. Removing .NET Framework installer." Delete "$TEMP\dotnetfx.exe" DetailPrint ".NET Framework installer removed." goto NewDotNet GiveUpDotNET: Abort "Installation cancelled by user." NewDotNET: DetailPrint "Proceeding with remainder of installation." Pop $7 Pop $6 Pop $5 Pop $4 Pop $3 Pop $2 Pop $1 Pop $0 !macroend