Check for .NET4.5+ with NSIS
Asked Answered
E

6

13

All, I am aware of the following methods to check the framework version in NSIS. For .NET4.0+ I currently use

Function IsDotNetInstalled

    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:
        ; No, something went wrong along the way.  Looks like the 
        ; proper .NET Framework isn't installed.  
        MessageBox MB_ICONEXCLAMATION "To install UserCost, Microsoft's .NET Framework v${DOT_MAJOR}.${DOT_MINOR} \
        (or higher) must be installed. Cannot proceed with the installation!"
        ${OpenURL} "${WWW_MS_DOTNET4}"
        Abort

    yesDotNet:
        ; Everything checks out. Proceed with the rest of the installation.

FunctionEnd

This works very well for .NET4.0, but I have now extended my application to utilise the async/await features and subsequently need users to install .NET4.5+. The above method is not suitable as the installation for .NET4.5 now does not use the regestry path 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\Policy" to store any new information, that is that path does not seem to hold a value that changes between .NET4.0 and 4.5. Now I have seen the following posts:

NSIS Installer with .NET 4.5

which uses the registry path/entry 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP' to do the checks. Now this also does bot work as the entry does not change from .NET4.0 to 4.5. I notice that there is and entry called 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319\SKUs.NETFramework,Version=v4.5' can I use this to check the Framework version invariably?

Is there an offical line of the way to check for .NET4.5 using NSIS?

Thanks for your time.


Note: subsequently some installation of .NET4.5 my users have performed have had registry values for

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full 

a DWORD value named Release was not 378389 but 378181. Making this change seemed to resolve the problem as the entry for the Release is not in the registry for .NET4.5 and below.

Ecphonesis answered 5/3, 2013 at 15:27 Comment(0)
E
25

Yes there is an official way to check if .NET Framework 4.5 is installed, even if it's not really friendly. From MSDN:

You can test whether the .NET Framework 4.5 or the .NET Framework 4 is installed by checking the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full subkey in the registry for a DWORD value named Release. The existence of this DWORD indicates that the .NET Framework 4.5 has been installed on that computer. The value of Release is a version number. To determine if the final release version of the .NET Framework 4.5 is installed, check for a value that is equal to or greater than 378389.

http://msdn.microsoft.com/en-us/library/hh925568.aspx

It means you first have to check if 4.0 is installed and then to check if there is a value named Release in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full, if so then 4.5 is already installed (I think you can skip the check for a pre-release version).

EDIT: check this post here on SO for details about detecting older installed .NET versions and this MSDN article to distinguish between for 4.5.x versions.

Enjoy answered 5/3, 2013 at 15:35 Comment(2)
That is a quality answer. Where is this information made avalible by Microsoft - or are we expected to find out ourselfs? Thanks for your time...Ecphonesis
I did forget to reference the source.Enjoy
A
5

Here is a function that I wrote that checks for, and downloads if needed, .NET 4.5. In addition, the code also looks for a local copy of the .NET installer - in case you were to put your installer onto a CD or USB drive or something. Supports Silent and Non-Silent installs, as well as setting the Reboot flag. The function is self-contained, but expects you to include LogicLib (which is included with the basic NSIS install).

This is the code that I wrote for what will be the installer for my Rachel's Story books.

Function CheckAndDownloadDotNet45
# Let's see if the user has the .NET Framework 4.5 installed on their system or not
# Remember: you need Vista SP2 or 7 SP1.  It is built in to Windows 8, and not needed
# In case you're wondering, running this code on Windows 8 will correctly return is_equal
# or is_greater (maybe Microsoft releases .NET 4.5 SP1 for example)

# Set up our Variables
Var /GLOBAL dotNET45IsThere
Var /GLOBAL dotNET_CMD_LINE
Var /GLOBAL EXIT_CODE

ReadRegDWORD $dotNET45IsThere HKLM "SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" "Release"
IntCmp $dotNET45IsThere 378389 is_equal is_less is_greater

is_equal:
    Goto done_compare_not_needed
is_greater:
    # Useful if, for example, Microsoft releases .NET 4.5 SP1
    # We want to be able to simply skip install since it's not
    # needed on this system
    Goto done_compare_not_needed
is_less:
    Goto done_compare_needed

done_compare_needed:
    #.NET Framework 4.5 install is *NEEDED*

    # Microsoft Download Center EXE:
    # Web Bootstrapper: http://go.microsoft.com/fwlink/?LinkId=225704
    # Full Download: http://go.microsoft.com/fwlink/?LinkId=225702

    # Setup looks for components\dotNET45Full.exe relative to the install EXE location
    # This allows the installer to be placed on a USB stick (for computers without internet connections)
    # If the .NET Framework 4.5 installer is *NOT* found, Setup will connect to Microsoft's website
    # and download it for you

    # Reboot Required with these Exit Codes:
    # 1641 or 3010

    # Command Line Switches:
    # /showrmui /passive /norestart

    # Silent Command Line Switches:
    # /q /norestart


    # Let's see if the user is doing a Silent install or not
    IfSilent is_quiet is_not_quiet

    is_quiet:
        StrCpy $dotNET_CMD_LINE "/q /norestart"
        Goto LookForLocalFile
    is_not_quiet:
        StrCpy $dotNET_CMD_LINE "/showrmui /passive /norestart"
        Goto LookForLocalFile

    LookForLocalFile:
        # Let's see if the user stored the Full Installer
        IfFileExists "$EXEPATH\components\dotNET45Full.exe" do_local_install do_network_install

        do_local_install:
            # .NET Framework found on the local disk.  Use this copy

            ExecWait '"$EXEPATH\components\dotNET45Full.exe" $dotNET_CMD_LINE' $EXIT_CODE
            Goto is_reboot_requested

        # Now, let's Download the .NET
        do_network_install:

            Var /GLOBAL dotNetDidDownload
            NSISdl::download "http://go.microsoft.com/fwlink/?LinkId=225704" "$TEMP\dotNET45Web.exe" $dotNetDidDownload

            StrCmp $dotNetDidDownload success fail
            success:
                ExecWait '"$TEMP\dotNET45Web.exe" $dotNET_CMD_LINE' $EXIT_CODE
                Goto is_reboot_requested

            fail:
                MessageBox MB_OK|MB_ICONEXCLAMATION "Unable to download .NET Framework.  ${PRODUCT_NAME} will be installed, but will not function without the Framework!"
                Goto done_dotNET_function

            # $EXIT_CODE contains the return codes.  1641 and 3010 means a Reboot has been requested
            is_reboot_requested:
                ${If} $EXIT_CODE = 1641
                ${OrIf} $EXIT_CODE = 3010
                    SetRebootFlag true
                ${EndIf}

done_compare_not_needed:
    # Done dotNET Install
    Goto done_dotNET_function

#exit the function
done_dotNET_function:

FunctionEnd
Analyzer answered 7/3, 2013 at 2:15 Comment(3)
No problem. I just finished writing the function for myself the other day, and stumbled across this page via Twitter and figured "why not?" I like your code, though mine does not present .NET as an option (since the program requires it). There's also the little bit that allows a local copy of the .NET installer to run, that allows your installer to be placed on a CD or USB key. I noticed that your code does not use /SD in your MessageBox calls (to allow for Silent operations - feel free to look over how I handle it).Analyzer
There is a problem with this code. "Variable "dotNetDidDownload" not referenced or never set". You should pop the returnvalue from the stack after the NSISdl::download call instead of supplying it as a parameter. Also StrCmp $dotNetDidDownload success fail should be StrCmp $dotNetDidDownload "success" success fail.Mosquito
You should probably mention the reference page to get numbers for other frameworks so it is usable by more people. The article above you mentions it people who like your flavor need the ref as well. learn.microsoft.com/en-us/dotnet/framework/migration-guide/…Carson
E
5

In the end I went with the following function which utilises the answer above. This method first creates a directory "$INSTDIR\dotNETFramework" which contains the .NET web installer:

Function CheckAndInstallDotNet
    ; Installer dotNetFx45_Full_setup.exe avalible from http://msdn.microsoft.com/en-us/library/5a4x27ek.aspx
    ; Magic numbers from http://msdn.microsoft.com/en-us/library/ee942965.aspx
    ClearErrors
    ReadRegDWORD $0 HKLM "SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" "Release"
    IfErrors NotDetected
    ${If} $0 >= 378389
        DetailPrint "Microsoft .NET Framework 4.5 is installed ($0)"
    ${Else}
    NotDetected:
        MessageBox MB_YESNO|MB_ICONQUESTION ".NET Framework 4.5+ is required for ProgramX2013, \
            do you want to launch the web installer? This requires a valid internet connection." IDYES InstallDotNet IDNO Cancel 
        Cancel:
            MessageBox MB_ICONEXCLAMATION "To install ProgramX, Microsoft's .NET Framework v${DOT_MAJOR}.${DOT_MINOR} \
                (or higher) must be installed. Cannot proceed with the installation!"
            ${OpenURL} "${WWW_MS_DOTNET4_5}"
            RMDir /r "$INSTDIR" 
            SetOutPath "$PROGRAMFILES"
            RMDir "$INSTDIR" 
            Abort

        ; Install .NET4.5.
        InstallDotNet:
            DetailPrint "Installing Microsoft .NET Framework 4.5"
            SetDetailsPrint listonly
            ExecWait '"$INSTDIR\dotNETFramework\dotNetFx45_Full_setup.exe" /passive /norestart' $0
            ${If} $0 == 3010 
            ${OrIf} $0 == 1641
                DetailPrint "Microsoft .NET Framework 4.5 installer requested reboot."
                SetRebootFlag true 
            ${EndIf}
            SetDetailsPrint lastused
            DetailPrint "Microsoft .NET Framework 4.5 installer returned $0"
    ${EndIf}

    ; Now remove the dotNETFramework directory and contents.
    RMDir /r "$INSTDIR\dotNETFramework" 
FunctionEnd

This method seemlessley launches the .NET4.5 installer if there is an internet connection and returns after the installation is complete.

I hope this helps someone else.

Ecphonesis answered 7/3, 2013 at 9:7 Comment(2)
@sa_ddam213 note I have just this second recived a client notice saying he is having trouble with running the .NET web installer automatically from XP. I am looking into this and will post a solution when/if I get one...Ecphonesis
See #11027685.Ecphonesis
A
4

Here's a simple NSIS Function that checks for .NET versions (works for 4.5, 4.5.1, 4.5.2 and 4.6). The numeric comparisons are based on MSDN.

Place the function in your NSIS file and invoke it like so

Call CheckForDotVersion45Up
Pop $0
DetailPrint $0

Here is the function.

; returns a numeric value on the stack, ranging from 0 to 450, 451, 452 or 460. 0 means nothing found, the other values mean at least that version
Function CheckForDotVersion45Up

  ReadRegDWORD $0 HKLM "SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" Release

  IntCmp $0 393295 is46 isbelow46 is46

  isbelow46:
  IntCmp $0 379893 is452 isbelow452 is452

  isbelow452:
  IntCmp $0 378675 is451 isbelow451 is451

  isbelow451:
  IntCmp $0 378389 is45 isbelow45 is45

  isbelow45:
  Push 0
  Return

  is46:
  Push 460
  Return

  is452:
  Push 452
  Return

  is451:
  Push 451
  Return

  is45:
  Push 45
  Return

FunctionEnd
Afterpiece answered 27/10, 2015 at 11:21 Comment(0)
P
1

Now that .NET Framework 4.5.1 is available the actual value of DWORD named Release in the registry needs to be checked, not just its existence.

A value of 378758 means that .NET Framework 4.5.1 is installed, however, as described here this value is 378675 on Windows 8.1.

Paladin answered 12/12, 2013 at 9:29 Comment(0)
D
1

If you're looking for options with .net framework 4.0+ (and above) including

  • .net 4.5
  • .net 4.5.1

you can also check this plug-in for NSIS: DotNetChecker

Daugavpils answered 7/10, 2014 at 1:49 Comment(2)
@Killercam Thanks for the heads up. Fixed it.Daugavpils
While that GitHub project can be useful, be aware that it by default tries to download the missing framework version. Something that may not be desirable in your installer.Cattery

© 2022 - 2024 — McMap. All rights reserved.