Сценарий PowerShell для возврата версий .NET Framework на компьютере? - PullRequest
157 голосов
/ 15 августа 2010

Что такое сценарий PowerShell для возврата версий .NET Framework на компьютере?

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

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

Ответы [ 13 ]

310 голосов
/ 16 августа 2010

Если вы собираетесь использовать реестр, вам нужно выполнить рекурсию, чтобы получить полную версию для 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's 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 }}
"@
26 голосов
/ 16 августа 2010
gci 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' |
sort pschildname -des                                  |
select -fi 1 -exp pschildname

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

21 голосов
/ 15 августа 2010
[environment]::Version

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

19 голосов
/ 19 октября 2017

Добавлена ​​поддержка 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" }
      }
    }
}
14 голосов
/ 05 июля 2013

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

[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   
9 голосов
/ 02 июня 2017

Я нашел это в дополнении табуляции в powershell for osx:

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

4 голосов
/ 15 августа 2010

Нет надежного способа сделать это для всех платформ и архитектур с помощью простого скрипта.Если вы хотите узнать, как сделать это надежно, начните с записи в блоге Обновленный пример кода обнаружения .NET Framework, который выполняет более глубокую проверку .

2 голосов
/ 29 августа 2018

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

Попробуйте использовать загружаемый 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 framework> = 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
2 голосов
/ 20 ноября 2014

См. Страницу Скрипт для определения, какие версии .NET установлены на удаленных рабочих станциях .

Скрипт, который может быть полезен для поиска версии .NETдля нескольких машин в сети.

2 голосов
/ 15 августа 2010

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...