Secuencia de comandos de PowerShell para devolver versiones de .NET Framework en una máquina?

¿Qué sería una secuencia de comandos de PowerShell para devolver versiones de .NET Framework en una máquina?

Mi primera suposición es algo relacionado con WMI. ¿Hay algo mejor?

Debería ser de una sola línea devolver solo la última versión para cada instalación de .NET [en cada línea].

Si va a utilizar el registro, debe recurrir para obtener la versión completa del Marco 4.x. Las respuestas anteriores devuelven el número raíz en mi sistema para .NET 3.0 (donde los números WCF y WPF, que están nesteds en 3.0, son más altos, no puedo explicar eso) y no devuelven nada para 4.0. .

EDITAR: para .Net 4.5 y versiones posteriores, esto cambió ligeramente nuevamente, por lo que ahora hay un buen artículo de MSDN que explica cómo convertir el valor de la versión a un número de versión .Net, es un accidente total del tren 🙁

Esto me parece correcto (nótese que emite números de versión separados para WCF y WPF en 3.0. No sé de qué se trata). También emite tanto Client como Full en 4.0 (si tiene ambas instaladas):

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 

Según el artículo de MSDN, puede crear una tabla de búsqueda y devolver el número de versión del producto de marketing para las versiones posteriores a 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' } 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 

De hecho, dado que tengo que actualizar esta respuesta, aquí hay un script para generar el guión anterior (con un poco más) del origen de la rebaja para esa página web. Es probable que esto se rompa en algún momento, por lo tanto, mantendré la copia actual arriba.

 # 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 }} "@ 
 gci 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' | sort pschildname -des | select -fi 1 -exp pschildname 

Esta respuesta no devuelve 4.5 si está instalada. La respuesta a continuación de @Jaykul y el uso de recurse lo hace.

 [environment]::Version 

Le da una instancia de la Version para el CLR que está usando la copia actual de PSH (como se documenta aquí ).

Corregir la syntax

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

La función GetSystemVersion devuelve una cadena como esta:

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

o así

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

$PSVersionTable es un objeto de solo lectura. La propiedad CLRVersion es un número de versión estructurada como este:

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

Se agregó compatibilidad con v4.7.2 al script:

 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" } {$_ -gt 461814} { [Version]"Undocumented version (> 4.7.2), please update script" } } } } 

Encontré esto a través de la finalización de tabs en powershell para osx:

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

No hay una manera confiable de hacer esto para todas las plataformas y architectures usando una secuencia de comandos simple. Si desea aprender cómo hacerlo de manera confiable, comience por la publicación del blog. Código de detección del marco de muestra actualizado de .NET que hace una comprobación más a fondo .

No es bonito. Definitivamente no es bonito:

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

Esto puede o no funcionar. Pero en lo que se refiere a la última versión, esto debería ser bastante confiable, ya que existen esencialmente carpetas vacías para las versiones anteriores (1.0, 1.1) pero no las más recientes, que solo aparecen una vez que se instala el marco apropiado.

Aún así, sospecho que debe haber una mejor manera.

Consulte la página Script para encontrar qué versiones de .NET están instaladas en estaciones de trabajo remotas .

El script allí podría ser útil para encontrar la versión .NET para múltiples máquinas en una red.

Buena solución

Intente utilizar el módulo descargable DotNetVersionLister (basado en las informaciones del registro y en alguna tabla de búsqueda de versión a comercialización).

Que se usaría así:

 PS> Get-DotNetVersion -LocalHost 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 : Script start time: 09/03/2018 09:21:18 Script end time: 09/03/2018 09:21:19 

O así si solo quieres probarlo para .NET framework> = 4. * :

 PS> (Get-DotNetVersion -LocalHost).">=4.x" Script start time: 09/03/2018 09:25:55 Script end time: 09/03/2018 09:25:55 4.5.2 

Pero no funcionará (instalar / importar), por ejemplo, con PS v2.0 ( Win 7 , estándar de Win Server 2010 ) debido a incompatibilidad …

Motivación para las funciones “heredadas” a continuación

(Puede omitir esta lectura y usar el código a continuación)

Tuvimos que trabajar con PS 2.0 en algunas máquinas y no pudimos instalar / importar el DotNetVersionLister anterior.
En otras máquinas, queríamos actualizar (desde PS 2.0 ) a PS 5.1 (que a su vez necesita .NET Framework> = 4.5 ) con la ayuda de dos compañías: Install-DotnetLatestCompany e Install-PSLatestCompany .
Para guiar a los administradores de manera agradable a través del proceso de instalación / actualización, deberíamos determinar la versión de .NET en estas funciones en todas las máquinas y versiones de PS existentes.
Por lo tanto, también utilizamos las funciones siguientes para determinarlas de forma más segura en todos los entornos …

Funciones para entornos de PS heredados (p. Ej. PS v2.0 )

Entonces, el siguiente código y los ejemplos de uso a continuación (extraídos) son útiles aquí (en base a otras respuestas aquí):

 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, eg 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 } } } 

Ejemplo de uso:

 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 

No estoy al tanto de mi syntax de PowerShell, pero creo que podría simplemente llamar a System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion () . Esto devolverá la versión como una cadena (algo así como v2.0.50727 , creo).

Aquí está la idea general:

Obtenga elementos secundarios en el directorio .NET Framework que son contenedores cuyos nombres coinciden con el número de punto del número de patrón v . Ordenarlos por nombre descendente, tomar el primer objeto y devolver su propiedad de nombre.

Aquí está el guión:

 (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 

¡Intentaré este en PowerShell: funcionó para mí!

(Get-ItemProperty “HKLM: Software \ Microsoft \ NET Framework Setup \ NDP \ v4 \ Full”). Versión