PowerShell script для возврата версий .NET Framework на машину?

Каким образом PowerShell script должен возвращать версии .NET Framework на машине?

Мое первое предположение - это что-то, что связано с WMI. Есть что-то лучше?

Он должен быть однострочным, чтобы возвращать только последнюю версию для каждой установки .NET [в каждой строке].

Ответ 1

Если вы собираетесь использовать реестр, вам нужно выполнить рекурсию, чтобы получить полную версию для 4.x Framework. Предыдущие ответы оба возвращают номер root в моей системе для .NET 3.0 (где номера WCF и WPF, вложенные в 3.0, выше - я не могу этого объяснить) и не возвращают ничего для 4.0..

ОБНОВЛЕНИЕ: Для .Net 4.5 и выше, это снова немного изменилось, так что теперь есть хорошая статья MSDN здесь, объясняющая, как преобразовать значение Release в номер версии .Net, это полное крушение поезда :-(

Это выглядит правильно для меня (обратите внимание, что он выводит отдельные номера версий для WCF и WPF на 3.0. Я не знаю, о чем это). Он также выводит как Client, так и Full на 4.0 (если они установлены):

Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -recurse |
Get-ItemProperty -name Version,Release -EA 0 |
Where { $_.PSChildName -match '^(?!S)\p{L}'} |
Select PSChildName, Version, Release

На основе статьи MSDN вы можете создать справочную таблицу и вернуть номер версии маркетингового продукта для выпусков после 4.5:

$Lookup = @{
    378389 = [version]'4.5'
    378675 = [version]'4.5.1'
    378758 = [version]'4.5.1'
    379893 = [version]'4.5.2'
    393295 = [version]'4.6'
    393297 = [version]'4.6'
    394254 = [version]'4.6.1'
    394271 = [version]'4.6.1'
    394802 = [version]'4.6.2'
    394806 = [version]'4.6.2'
    460798 = [version]'4.7'
    460805 = [version]'4.7'
    461308 = [version]'4.7.1'
    461310 = [version]'4.7.1'
    461808 = [version]'4.7.2'
    461814 = [version]'4.7.2'
    528040 = [version]'4.8'
    528049 = [version]'4.8'
}

# For One True framework (latest .NET 4x), change the Where-Oject match 
# to PSChildName -eq "Full":
Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse |
  Get-ItemProperty -name Version, Release -EA 0 |
  Where-Object { $_.PSChildName -match '^(?!S)\p{L}'} |
  Select-Object @{name = ".NET Framework"; expression = {$_.PSChildName}}, 
@{name = "Product"; expression = {$Lookup[$_.Release]}}, 
Version, Release

Фактически, поскольку мне постоянно приходится обновлять этот ответ, здесь приведен скрипт для генерации сценария выше (с небольшим дополнительным дополнением) из источника уценки для этой веб-страницы. Возможно, в какой-то момент это сломается, поэтому я сохраняю текущую копию выше.

# Get the text from github
$url = "https://raw.githubusercontent.com/dotnet/docs/master/docs/framework/migration-guide/how-to-determine-which-versions-are-installed.md"
$md = Invoke-WebRequest $url -UseBasicParsing
$OFS = "'n"
# Replace the weird text in the tables, and the padding
# Then trim the | off the front and end of lines
$map = $md -split "'n" -replace " installed [^|]+" -replace "\s+\|" -replace "\|$" |
    # Then we can build the table by looking for unique lines that start with ".NET Framework"
    Select-String "^.NET" | Select-Object -Unique |
    # And flip it so it key = value
    # And convert ".NET FRAMEWORK 4.5.2" to  [version]4.5.2
    ForEach-Object { 
        [version]$v, [int]$k = $_ -replace "\.NET Framework " -split "\|"
        "    $k = [version]'$v'"
    }

# And output the whole script
@"
'$Lookup = @{
$map
}

# For extra effect we could get the Windows 10 OS version and build release id:
try {
    '$WinRelease, '$WinVer = Get-ItemPropertyValue "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" ReleaseId, CurrentMajorVersionNumber, CurrentMinorVersionNumber, CurrentBuildNumber, UBR
    '$WindowsVersion = "'$('$WinVer -join '.') ('$WinRelease)"
} catch {
    '$WindowsVersion = [System.Environment]::OSVersion.Version
}

Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse |
    Get-ItemProperty -name Version, Release -EA 0 |
    # For The One True framework (latest .NET 4x), change match to PSChildName -eq "Full":
    Where-Object { '$_.PSChildName -match '^(?!S)\p{L}'} |
    Select-Object @{name = ".NET Framework"; expression = {'$_.PSChildName}}, 
                @{name = "Product"; expression = {'$Lookup['$_.Release]}}, 
                Version, Release,
    # Some OPTIONAL extra output: PSComputerName and WindowsVersion
    # The Computer name, so output from local machines will match remote machines:
    @{ name = "PSComputerName"; expression = {'$Env:Computername}},
    # The Windows Version (works on Windows 10, at least):
    @{ name = "WindowsVersion"; expression = { '$WindowsVersion }}
"@

Ответ 2

gci 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' |
sort pschildname -des                                  |
select -fi 1 -exp pschildname

Этот ответ не возвращает 4.5, если он установлен. Ответ ниже от @Jaykul и использование recurse.

Ответ 3

[environment]::Version

Дает вам экземпляр Version для CLR, который использует текущая копия PSH (как описано здесь).

Ответ 4

Добавлена поддержка v4.8 для скрипта:

Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -recurse |
Get-ItemProperty -name Version,Release -EA 0 |
Where { $_.PSChildName -match '^(?![SW])\p{L}'} |
Select PSChildName, Version, Release, @{
  name="Product"
  expression={
      switch -regex ($_.Release) {
        "378389" { [Version]"4.5" }
        "378675|378758" { [Version]"4.5.1" }
        "379893" { [Version]"4.5.2" }
        "393295|393297" { [Version]"4.6" }
        "394254|394271" { [Version]"4.6.1" }
        "394802|394806" { [Version]"4.6.2" }
        "460798|460805" { [Version]"4.7" }
        "461308|461310" { [Version]"4.7.1" }
        "461808|461814" { [Version]"4.7.2" }
        "528040|528049" { [Version]"4.8" }
        {$_ -gt 528049} { [Version]"Undocumented version (> 4.8), please update script" }
      }
    }
}

Ответ 5

Правильный синтаксис:

[System.Runtime.InteropServices.RuntimeEnvironment]::GetSystemVersion()
#or
$PSVersionTable.CLRVersion

Функция GetSystemVersion возвращает следующую строку:

v2.0.50727        #PowerShell v2.0 in Win 7 SP1

или как это

v4.0.30319        #PowerShell v3.0 (Windows Management Framework 3.0) in Win 7 SP1

$PSVersionTable является объектом только для чтения. Свойство CLRVersion представляет собой структурированный номер версии, подобный этому:

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      30319  18444   

Ответ 6

Я нашел это через вкладку завершения в powershell для osx:

[System.Runtime.InteropServices.RuntimeInformation]::get_FrameworkDescription() .NET Core 4.6.25009.03

Ответ 8

Не очень. Определенно не красиво:

ls $Env:windir\Microsoft.NET\Framework | ? { $_.PSIsContainer } | select -exp Name -l 1

Это может работать или не работать. Но, что касается последней версии, это должно быть довольно надежным, поскольку по умолчанию существуют пустые папки для старых версий (1.0, 1.1), но не более новые - они появляются только после установки соответствующей структуры.

Тем не менее, я подозреваю, что должен быть лучший способ.

Ответ 10

Хорошее решение

Попробуйте использовать загружаемый модуль DotNetVersionLister (на основе информации реестра и таблицы поиска версий от маркетинговой версии).

Который будет использоваться так:

PS> Get-DotNetVersion -LocalHost -nosummary


ComputerName : localhost
>=4.x        : 4.5.2
v4\Client    : Installed
v4\Full      : Installed
v3.5         : Installed
v3.0         : Installed
v2.0.50727   : Installed
v1.1.4322    : Not installed (no key)
Ping         : True
Error        :

Или вот так, если вы просто хотите протестировать его на какой-то платформе .NET> = 4. *:

PS> (Get-DotNetVersion -LocalHost -nosummary).">=4.x"
4.5.2

Но это не будет работать (установка/импорт), например, с PS v2.0 (Win 7, стандарт Win Server 2010) из-за несовместимости...

Мотивация для "наследственных" функций ниже

(Вы можете пропустить чтение и использовать код ниже)

Нам приходилось работать с PS 2.0 на некоторых машинах, и мы не смогли установить/импортировать вышеупомянутый DotNetVersionLister.
На других машинах мы хотели обновить (с PS 2.0) до PS 5.1 (который в свою очередь нуждается в .NET Framework> = 4.5) с помощью двух пользовательских- Install-DotnetLatestCompany и Install-PSLatestCompany.
Чтобы хорошо провести администраторов через процесс установки/обновления, нам нужно определить версию .NET в этих функциях на всех машинах и существующих версиях PS.
Таким образом, мы использовали также следующие функции, чтобы определить их более безопасно во всех средах...

Функции для устаревших сред PS (например, PS v2.0)

Поэтому следующий код и приведенные ниже (извлеченные) примеры использования полезны здесь (на основе других ответов здесь):

function Get-DotNetVersionByFs {
  <#
    .SYNOPSIS
      NOT RECOMMENDED - try using instead:
        Get-DotNetVersion 
          from DotNetVersionLister module (https://github.com/EliteLoser/DotNetVersionLister), 
          but it is not usable/importable in PowerShell 2.0 
        Get-DotNetVersionByReg
          reg(istry) based: (available herin as well) but it may return some wrong version or may not work reliably for versions > 4.5 
          (works in PSv2.0)
      Get-DotNetVersionByFs (this):  
        f(ile) s(ystem) based: determines the latest installed .NET version based on $Env:windir\Microsoft.NET\Framework content
        this is unreliable, e.g. if 4.0* is already installed some 4.5 update will overwrite content there without
        renaming the folder
        (works in PSv2.0)
    .EXAMPLE
      PS> Get-DotnetVersionByFs
      4.0.30319
    .EXAMPLE
      PS> Get-DotnetVersionByFs -All
      1.0.3705
      1.1.4322
      2.0.50727
      3.0
      3.5
      4.0.30319
    .NOTES
      from https://stackoverflow.com/a/52078523/1915920
  #>
    [cmdletbinding()]
  param(
    [Switch]$All  ## do not return only latest, but all installed
  )
  $list = ls $Env:windir\Microsoft.NET\Framework |
    ?{ $_.PSIsContainer -and $_.Name -match '^v\d.[\d\.]+' } |
    %{ $_.Name.TrimStart('v') }
  if ($All) { $list } else { $list | select -last 1 }
}


function Get-DotNetVersionByReg {
  <#
    .SYNOPSIS
      NOT RECOMMENDED - try using instead:
        Get-DotNetVersion
          From DotNetVersionLister module (https://github.com/EliteLoser/DotNetVersionLister), 
          but it is not usable/importable in PowerShell 2.0. 
          Determines the latest installed .NET version based on registry infos under 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP'
    .EXAMPLE
        PS> Get-DotnetVersionByReg
        4.5.51209
    .EXAMPLE
        PS> Get-DotnetVersionByReg -AllDetailed
        PSChildName                                          Version                                             Release
        -----------                                          -------                                             -------
        v2.0.50727                                           2.0.50727.5420
        v3.0                                                 3.0.30729.5420
        Windows Communication Foundation                     3.0.4506.5420
        Windows Presentation Foundation                      3.0.6920.5011
        v3.5                                                 3.5.30729.5420
        Client                                               4.0.0.0
        Client                                               4.5.51209                                           379893
        Full                                                 4.5.51209                                           379893
    .NOTES
      from https://stackoverflow.com/a/52078523/1915920
  #>
    [cmdletbinding()]
    param(
        [Switch]$AllDetailed  ## do not return only latest, but all installed with more details
    )
    $Lookup = @{
        378389 = [version]'4.5'
        378675 = [version]'4.5.1'
        378758 = [version]'4.5.1'
        379893 = [version]'4.5.2'
        393295 = [version]'4.6'
        393297 = [version]'4.6'
        394254 = [version]'4.6.1'
        394271 = [version]'4.6.1'
        394802 = [version]'4.6.2'
        394806 = [version]'4.6.2'
        460798 = [version]'4.7'
        460805 = [version]'4.7'
        461308 = [version]'4.7.1'
        461310 = [version]'4.7.1'
        461808 = [version]'4.7.2'
        461814 = [version]'4.7.2'
    }
    $list = Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse |
        Get-ItemProperty -name Version, Release -EA 0 |
        # For One True framework (latest .NET 4x), change match to PSChildName -eq "Full":
        Where-Object { $_.PSChildName -match '^(?!S)\p{L}'} |
        Select-Object '
           @{
               name = ".NET Framework" ; 
               expression = {$_.PSChildName}}, 
           @{  name = "Product" ; 
               expression = {$Lookup[$_.Release]}}, 
           Version, Release
    if ($AllDetailed) { $list | sort version } else { $list | sort version | select -last 1 | %{ $_.version } }
}

Пример использования:

PS> Get-DotNetVersionByFs
4.0.30319

PS> Get-DotNetVersionByFs -All
1.0.3705
1.1.4322
2.0.50727
3.0
3.5
4.0.30319

PS> Get-DotNetVersionByReg
4.5.51209

PS> Get-DotNetVersionByReg -AllDetailed

.NET Framework                   Product Version        Release
--------------                   ------- -------        -------
v2.0.50727                               2.0.50727.5420
v3.0                                     3.0.30729.5420
Windows Communication Foundation         3.0.4506.5420
Windows Presentation Foundation          3.0.6920.5011
v3.5                                     3.5.30729.5420
Client                                   4.0.0.0
Client                           4.5.2   4.5.51209      379893
Full                             4.5.2   4.5.51209      379893

Ответ 11

Если вы установили Visual Studio на свой компьютер, откройте командную строку разработчика Visual Studio и введите следующую команду: clrver

В нем будут перечислены все установленные версии .NET Framework на этом компьютере.

Ответ 12

Здесь общая идея:

Получить дочерние элементы в каталоге .NET Framework, которые являются контейнерами, имена которых соответствуют образец v число число число. Сортируйте их по нисходящему имени, возьмите первый объект, и вернуть его свойство name.

Здесь script:

(Get-ChildItem -Path $Env:windir\Microsoft.NET\Framework | Where-Object {$_.PSIsContainer -eq $true } | Where-Object {$_.Name -match 'v\d\.\d'} | Sort-Object -Property Name -Descending | Select-Object -First 1).Name

Ответ 13

Я бы попробовал это в PowerShell: Работал для меня!

(Get-ItemProperty "HKLM: Программное обеспечение \Microsoft\NET Framework Setup\NDP\v4\Full"). Версия