DotNET: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
(I re-wrote DotNet.nsh to actually check version numbers. The install is also silent now, so no need for the dll)
(→‎Script: My latest DotNET, based on the original but much more robust and user-friendly)
Line 42: Line 42:
<highlight-nsis>
<highlight-nsis>
# DotNET version checking macro.
# DotNET version checking macro.
# Written by AnarkiNet(AnarkiNet@gmail.com) originally, modified by eyal0
# Written by AnarkiNet(AnarkiNet@gmail.com) originally, modified by eyal0 (for use in http://www.sourceforge.net/projects/itwister)
# Downloads and runs the Microsoft .NET Framework version 2.0 Redistributable 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.
;modifies the input to a version that can be compared like a string or num
# To use, call the macro with a string:
!macro VerToNum VTN_output VTN_version
# !insertmacro CheckDotNET "2"
   ;MessageBox MB_OK "***VTN_version is ${VTN_version}"
# !insertmacro CheckDotNET "2.0.9"
# (Version 2.0.9 is less than version 2.0.10.)
# 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"
   DetailPrint "Checking your .NET Framework version..."
  ;callee register save
   Push $0
   Push $0
   Push $1
   Push $1
Line 52: Line 60:
   Push $3
   Push $3
   Push $4
   Push $4
    
   Push $5
   StrCpy $4 ${VTN_version}
   Push $6 ;backup of intsalled ver
   StrCpy $0 ""
   Push $7 ;backup of DoNetReqVer
   StrCpy $1 0
 
  ;MessageBox MB_OK "3**VTN_version is $4"
   StrCpy $7 ${DotNetReqVer}


   ${DoUntil} $1 == 4
   System::Call "mscoree::GetCORVersion(w .r0, i ${NSIS_MAX_STRLEN}, *i r2r2) i .r1 ?u"
    ;MessageBox MB_OK "4**VTN_version is $4"
 
    ${StrTok} $2 $4 "." $1 "0"
  ${If} $0 == 0
    ;MessageBox MB_OK "***VTN_version is now $4"
  DetailPrint ".NET Framework not found, download is required for program to run."
    ;MessageBox MB_OK "***0 is $0"
     Goto NoDotNET
    ;MessageBox MB_OK "***1 is $1"
  ${EndIf}
     StrLen $3 $2
 
    ${DoUntil} $3 >= 6 ;until the current part is 6 digits long
  ;at this point, $0 has maybe v2.345.678.
      ;MessageBox MB_OK "2 is $2"
  StrCpy $0 $0 $2 1 ;remove the starting "v", $0 has the installed version num as a string
      StrCpy $2 "0$2"
  StrCpy $6 $0
      StrLen $3 $2
  StrCpy $1 $7 ;$1 has the requested verison num as a string
    ${Loop}
    StrCpy $0 $0$2
    IntOp $1 $1 + 1
  ${Loop}


   Pop $4
   ;MessageBox MB_OKCANCEL "found $0" \
   Pop $3
   ;  IDCANCEL GiveUpDotNET
  Pop $2
   
   Pop $1
   ;MessageBox MB_OKCANCEL "looking for $1" \
   Exch $0
   ;  IDCANCEL GiveUpDotNET
  Pop ${VTN_output}
!macroend


!macro CheckDotNET
   ;now let's compare the versions, installed against required <part0>.<part1>.<part2>.
   !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"
   ${Do}
   DetailPrint "Checking your .NET Framework version..."
    StrCpy $2 "" ;clear out the installed part
  Push $0
    StrCpy $3 "" ;clear out the required part
  Push $1


  System::Call "mscoree::GetCORVersion(w .r0, i ${NSIS_MAX_STRLEN}, *i) i .r1 ?u"
    ${Do}
  StrCmp $1 0 +2
      ${If} $0 == "" ;if there are no more characters in the version
    StrCpy $0 "not found"
        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}


  Pop $1
      ${If} $4 == "." ;if we're at the end of the current installed part
  Exch $0
        StrCpy $2 "0$2" ;put a zero on the front
  Pop $0
      ${Else} ;we have another character
  ${If} $0 == "not found"
        StrCpy $2 "$2$4" ;put the next character on the back
  DetailPrint ".NET Framework not found, download is required for program to run!"
      ${EndIf}
    Goto InvalidDotNET
      ${If} $5 == "." ;if we're at the end of the current required part
  ${EndIf}
        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


  ;at this point, $0 has maybe v2.345.678.
    ${If} $0 != "" ;let's remove the leading period on installed part if it exists
  Push $0
      StrCpy $0 $0 ${NSIS_MAX_STRLEN} 1
  Push $1
    ${EndIf}
  StrCpy $0 $0 ${NSIS_MAX_STRLEN} 1 ;remove the starting "v", $0 has the installed version num
    ${If} $1 != "" ;let's remove the leading period on required part if it exists
  StrCpy $1 ${DOTNET_VERSION}       ;$1 has the requested verison num
      StrCpy $1 $1 ${NSIS_MAX_STRLEN} 1
  !insertmacro VerToNum $0 $0 ;convert $0 to a 16 digit num
    ${EndIf}
  !insertmacro VerToNum $1 $1 ;convert $1 to a 16 digit num


  ${If} $0 S< $1
    ;$2 has the installed part, $3 has the required part
     Pop $1
    ${If} $2 S< $3
    Pop $0
      IntOp $0 0 - 1 ;$0 = -1, installed less than required
    DetailPrint ".NET Framework Version found: $0, but does not match required version: ${DOTNET_VERSION}"
      ${ExitDo}
     Goto InvalidDotNET
     ${ElseIf} $2 S> $3
  ${EndIf}
      IntOp $0 0 + 1 ;$0 = 1, installed greater than required
  Pop $1
      ${ExitDo}
  Pop $0
    ${ElseIf} $2 == ""
  DetailPrint ".NET Framework Version found: $0, matches required version: ${DOTNET_VERSION}."
     ${AndIf} $3 == ""
   Goto ValidDotNET
      IntOp $0 0 + 0 ;$0 = 0, the versions are identical
      ${ExitDo}
    ${EndIf} ;otherwise we just keep looping through the parts
   ${Loop}


InvalidDotNET:
   ${If} $0 < 0
   ${If} $0 == "not found"
     DetailPrint ".NET Framework Version found: $6, but is older than the required version: $7"
    MessageBox MB_YESNO|MB_ICONEXCLAMATION \
     Goto OldDotNET
     ".NET Framework not installed.$\nRequired Version: ${DOTNET_VERSION} or greater.$\nWould you like the installer to download the latest .NET Framework version from www.microsoft.com?" \
     IDYES Download IDNO ValidDotNET 
   ${Else}
   ${Else}
     MessageBox MB_YESNO|MB_ICONEXCLAMATION \
     DetailPrint ".NET Framework Version found: $6, equal or newer to required version: $7."
    "Your .NET Framework version: $0.$\nRequired Version: ${DOTNET_VERSION} or greater.$\nWould you like the installer to download the latest .NET Framework version from www.microsoft.com?" \
     Goto NewDotNET
     IDYES Download IDNO ValidDotNET
   ${EndIf}
   ${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
   
   
Download:
DownloadDotNET:
   DetailPrint "Beginning download of latest .NET Framework version."
   DetailPrint "Beginning download of latest .NET Framework version."
   NSISDL::download ${DOTNET_URL} "$TEMP\dotnetfx.exe"
   NSISDL::download ${DOTNET_URL} "$TEMP\dotnetfx.exe"
   DetailPrint "Completed download."
   DetailPrint "Completed download."
   Pop $R0
   Pop $0
   StrCmp $R0 "success" +2
   ${If} $0 == "cancel"
     Abort "Download failed: $R0"
    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."
   DetailPrint "Pausing installation while downloaded .NET Framework installer runs."
   ExecWait 'dotnetfx.exe /q /c:"install /q"'
   ExecWait 'dotnetfx.exe /q /c:"install /q"'
   DetailPrint "Completed .NET Framework install/update. Cleaning temporary files..."
   DetailPrint "Completed .NET Framework install/update. Removing .NET Framework installer."
   Delete "$TEMP\dotnetfx.exe"
   Delete "$TEMP\dotnetfx.exe"
   DetailPrint "Completed cleaning temporary files."
   DetailPrint ".NET Framework installer removed."
 
GiveUpDotNET:
  Abort "Installation cancelled by user."


ValidDotNET:
NewDotNET:
   DetailPrint "Proceeding with remainder of installation..."
   DetailPrint "Proceeding with remainder of installation."
  Pop $0
  Pop $1
  Pop $2
  Pop $3
  Pop $4
  Pop $5
  Pop $6 ;backup of intsalled ver
  Pop $7 ;backup of DoNetReqVer
!macroend
!macroend
</highlight-nsis></div>
</highlight-nsis></div>

Revision as of 10:13, 15 January 2007

Overview

DotNET is a macro written to aid in the deployment of .NET Framework 2.0-based applications using NSIS.

What it does

  1. Checks the version of the .NET framework on the end-user's computer.
  2. Prompts them with a yes/no dialog if their version is different than the defined DOTNET_VERSION in the installer's main script.
  3. If they press yes, the installer downloads the latest .NET Framework 2.0 installer and runs it.

Limitations

  • Only works for .NET Framework 2.0, not 1.0 or 1.1.

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
 
	#Files here
SectionEnd

Script

# DotNET version checking macro.
# Written by AnarkiNet(AnarkiNet@gmail.com) originally, modified by eyal0 (for use in http://www.sourceforge.net/projects/itwister)
# 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:
# !insertmacro CheckDotNET "2"
# !insertmacro CheckDotNET "2.0.9"
# (Version 2.0.9 is less than version 2.0.10.)
# 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"
  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
 
  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 '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."
 
GiveUpDotNET:
  Abort "Installation cancelled by user."
 
NewDotNET:
  DetailPrint "Proceeding with remainder of installation."
  Pop $0
  Pop $1
  Pop $2
  Pop $3
  Pop $4
  Pop $5
  Pop $6 ;backup of intsalled ver
  Pop $7 ;backup of DoNetReqVer
!macroend