Monday, December 18, 2017

PowerShell oneliner to list all the installed .NET versions on a local computer

In my drawers of PowerShell tools, I have a pretty extensive list of oneliners I have written for specific tasks. Today I want to share the line of code I wrote to check the .NET version installed on a local system. Since there is no direct method to find that information, a lot of people have come up with advanced functions, which is a bit overkill to me. So, given the fact that I like playing with the pipeline, and that I needed a quick and dirty script for this, I decided to see if I could find a way to get this done in just one line of code.

Starting from .NET 1.1 the registry key where the list of installed frameworks is installed is found under:
HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP
Under this key, you'll see separate keys for each .NET Framework version installed in your system.

Possible paths are:
1.1 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v1.1.4322
2.0 HKEY_LOCAL_MACHINE\Software\Microsoft\NET Framework Setup\NDP\v2.0.50727
3.0 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.0
3.5 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5
4.0 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
4.5 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
4.5.1 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
4.5.2 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
4.6 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
4.6.1 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
4.6.2 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
As you can see, there are five possible unique paths.

These can be matched with a regular expression:
v1.1.4322$|v2.0.50727$|v3.0$|v3.5$|v4\\Full$
which excludes v4.0 because it is deprecated.

Having PowerShell native access to the registry, we can run the following line on our local computer:
ls 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP'
just like you'd be browsing your file system.

Now what you have to know is that each .NET framework has a version name and a version number:
  • .NET version name is composed by digits, and comes with the product name i.e. .NET 2.0, .NET 3.5, .NET 4.7.1
  • .NET Version number follows this convention: (Major version).(Minor version).(Revision number).(Build number)

Here's some version numbers I have in my environment:

  • 4.7.02053
  • 4.5.51209
  • 3.5.30729.01
  • 2.1.21022

As you can see version names and version numbers share the first two fields. So, for istance, .NET 4.7.1 has version number 4.7.02556. We can then say that we don't care about the revision or build numbers (third and fourth field). The first two fields are all that I need.

To make a long story short, here's the PowerShell oneliner that I need to run to locally get all the installed .NET releases:
((ls 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -rec|? name -match 'v1.1.4322$|v2.0.50727$|v3.0$|v3.5$|v4\\Full$').name -replace 'HKEY_LOCAL_MACHINE','HKLM:'|%{ Get-ItemProperty $_}).Version
Hope this helps guys. Let me know in the comments if somebody here is able to make my oneliner shorter.

UPDATE: On older PowerShell version use:
((ls 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -rec|? {$_.name -match 'v1.1.4322$|v2.0.50727$|v3.0$|v3.5$|v4\\Full$'} | select -expand name) -replace 'HKEY_LOCAL_MACHINE','HKLM:') -replace 'HKEY_LOCAL_MACHINE','HKLM:'|%{ Get-ItemProperty $_} | select -expand Version

UPDATE: You can also specify this registry path by specifying the registry provider's name, followed by "::". The registry provider's full name is Microsoft.PowerShell.Core\Registry, but this can be shortened to just Registry. So the following syntax is also possible
((ls 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -rec|? name -match 'v1.1.4322$|v2.0.50727$|v3.0$|v3.5$|v4\\Full$').name |%{ Get-ItemProperty "Registry::$($_)"}).Version

4 comments:

  1. Hi I would like to suggest

    ls 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse | % { Get-ItemProperty -Path Registry::$($_.Name) } | Select Version -Unique

    because it does not depend on a hardcoded -match that would have to be updated for every new .NET release. Instead this should work for future versions as well.

    ReplyDelete
  2. I do not really understand but at least this article can provide references and new information for me

    ReplyDelete
  3. The one-liner doesn't seem to catch everything (particularly 4.0.0.0 which may be intentional since it should be integrated into any modern Windows version) but here's what I've been using:

    Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\*\*' | Where-Object Version | Select-Object Version -Unique | Sort-Object Version

    ReplyDelete
  4. why not just ask add remove programs via win32_product - obviously not the fastest method, but pretty straight forward:
    gwmi win32_product -filter "name like '%.NET%'" -computer $computername | select name, version
    this will work remotely as well if there is access
    or without powershell
    wmic /node:%computername% product get description | find /i ".NET"

    the only odd thing with this method is .NET 4.5 can be installed but it sometimes will show in ARP as Microsoft .NET Framework 4 Multi-Targeting Pack 4.0.30319

    you can also do this for servers
    get-windowsfeature NET-Framework-45-Features to confirm .NET 4.5 is installed

    ReplyDelete

Related Posts Plugin for WordPress, Blogger...