用于返回机器上 .NET Framework 版本的 PowerShell 脚本?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3487265/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PowerShell script to return versions of .NET Framework on a machine?
提问by MattUebel
What would a PowerShell script be to return versions of the .NET Framework on a machine?
在机器上返回 .NET Framework 版本的 PowerShell 脚本是什么?
My first guess is something involving WMI. Is there something better?
我的第一个猜测是涉及 WMI。有什么更好的吗?
It should be a one-liner to return only the latest version for each installation of .NET [on each line].
它应该是单行的,只为每次安装 .NET [在每一行] 返回最新版本。
回答by Jaykul
If you're going to use the registry you have to recurse in order to get the full version for the 4.x Framework. The earlier answers both return the root number on my system for .NET 3.0 (where the WCF and WPF numbers, which are nested under 3.0, are higher -- I can't explain that), and fail to return anything for 4.0 ...
如果您要使用注册表,则必须递归才能获得 4.x 框架的完整版本。较早的答案都返回我系统上 .NET 3.0 的根编号(其中嵌套在 3.0 下的 WCF 和 WPF 编号更高——我无法解释这一点),并且无法为 4.0 返回任何内容.. .
EDIT: For .Net 4.5 and up, this changed slightly again, so there's now a nice MSDN article hereexplaining how to convert the Releasevalue to a .Net version number, it's a total train wreck :-(
编辑:对于 .Net 4.5 及更高版本,这又略有变化,所以现在有一篇很好的MSDN 文章在这里解释了如何将Release值转换为 .Net 版本号,这完全是火车失事:-(
This looks right to me (note that it outputs separate version numbers for WCF & WPF on 3.0. I don't know what that's about). It also outputs both Clientand Fullon 4.0 (if you have them both installed):
这在我看来是正确的(请注意,它在 3.0 上为 WCF 和 WPF 输出单独的版本号。我不知道那是什么意思)。它还在 4.0 上同时输出Client和Full(如果您都安装了它们):
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
Based on the MSDN article, you could build a lookup table and return the marketing product version number for releases after 4.5:
根据 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-Object 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
In fact, since I keep having to update this answer, here's a script to generate the script above (with a little extra) from the markdown source for that web page. This will probably break at some point, so I'm keeping the current copy above.
事实上,由于我一直不得不更新这个答案,这里有一个脚本可以从该网页的降价源生成上面的脚本(有一点额外的)。这可能会在某个时候中断,所以我保留上面的当前副本。
# 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 }}
"@
回答by Jason Stangroome
gci 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' |
sort pschildname -des |
select -fi 1 -exp pschildname
This answer doesn't return 4.5 if that is installed. The answer below from @Jaykul and using recurse does.
如果已安装,此答案不会返回 4.5。以下来自@Jaykul 和使用递归的答案确实如此。
回答by AlexBar
Added v4.8 support to the script:
为脚本添加了 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" }
}
}
}
回答by Richard
回答by Desmond Lee
Correct syntax:
正确的语法:
[System.Runtime.InteropServices.RuntimeEnvironment]::GetSystemVersion()
#or
$PSVersionTable.CLRVersion
The GetSystemVersionfunction returns a string like this:
该GetSystemVersion函数返回这样的字符串:
v2.0.50727 #PowerShell v2.0 in Win 7 SP1
or like this
或者像这样
v4.0.30319 #PowerShell v3.0 (Windows Management Framework 3.0) in Win 7 SP1
$PSVersionTableis a read-only object. The CLRVersion property is a structured version number like this:
$PSVersionTable是一个只读对象。CLRVersion 属性是一个结构化的版本号,如下所示:
Major Minor Build Revision
----- ----- ----- --------
4 0 30319 18444
回答by js2010
I found this through tab completion in powershell for osx:
我通过 osx 的 powershell 中的选项卡完成发现了这一点:
[System.Runtime.InteropServices.RuntimeInformation]::get_FrameworkDescription()
.NET Core 4.6.25009.03
[System.Runtime.InteropServices.RuntimeInformation]::get_FrameworkDescription()
.NET Core 4.6.25009.03
回答by x0n
There's no reliable way to do this for all platforms and architectures using a simple script. If you want to learn how to do it reliably, start at the blog post Updated sample .NET Framework detection code that does more in-depth checking.
对于使用简单脚本的所有平台和体系结构,没有可靠的方法来执行此操作。如果您想了解如何可靠地执行此操作,请从博客文章更新的进行更深入检查的示例 .NET Framework 检测代码开始。
回答by kalidoss
Refer to the page Script for finding which .NET versions are installed on remote workstations.
请参阅页面脚本以查找远程工作站上安装了哪些 .NET 版本。
The script there might be useful to find the .NET version for multiple machines on a network.
那里的脚本对于查找网络上多台机器的 .NET 版本可能很有用。
回答by Andreas Dietrich
Nice solution
不错的解决方案
Try using the downloadable DotNetVersionListermodule(based on registry infos and some version-to-marketing-version lookup table).
尝试使用可下载的DotNetVersionLister模块(基于注册表信息和一些版本到营销版本查找表)。
Which would be used like this:
这将像这样使用:
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 :
Or like this if you just want to test it for some .NET framework >= 4.*:
或者像这样,如果你只是想测试一些.NET 框架 >= 4.*:
PS> (Get-DotNetVersion -LocalHost -nosummary).">=4.x"
4.5.2
But it will not work (install/import) e.g. with PS v2.0(Win 7, Win Server 2010standard) due to incompatibility...
但由于不兼容,它无法工作(安装/导入),例如使用PS v2.0(Win 7,Win Server 2010标准)...
Motivation for "legacy" functions below
下面是“遗留”功能的动机
(You could skip reading this and use code below)
(您可以跳过阅读本文并使用下面的代码)
We had to work with PS 2.0on some machines and could not install/import the above DotNetVersionLister.
On other machines we wanted to update (from PS 2.0) to PS 5.1(which in turn needs .NET Framework >= 4.5) with the help of two company-custom Install-DotnetLatestCompanyand Install-PSLatestCompany.
To guide admins nicely through the install/update process we would have to determine the .NET version in these functions on all machines and PS versions existing.
Thus we used also the below functions to determine them more safely in all environments...
我们不得不在某些机器上使用PS 2.0并且无法安装/导入上述DotNetVersionLister。
在其它机器上,我们要(从更新PS 2.0),以PS 5.1(而这又需要.NET框架> = 4.5)两个公司定制的帮助Install-DotnetLatestCompany和Install-PSLatestCompany。
为了在安装/更新过程中很好地指导管理员,我们必须确定所有机器和现有 PS 版本上这些功能中的 .NET 版本。
因此,我们还使用以下函数在所有环境中更安全地确定它们......
Functions for legacy PS environments (e.g. PS v2.0)
传统 PS 环境的功能(例如PS v2.0)
So the following code and below (extracted) usage examples are useful here (based on other answers here):
因此,以下代码和以下(提取的)用法示例在这里很有用(基于此处的其他答案):
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 } }
}
Example usage:
用法示例:
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
回答by Joey
Not pretty. Definitelynot pretty:
不漂亮。绝对不漂亮:
ls $Env:windir\Microsoft.NET\Framework | ? { $_.PSIsContainer } | select -exp Name -l 1
This may or may not work. But as far as the latest version is concerned this should be pretty reliable, as there are essentially empty folders for old versions (1.0, 1.1) but not newer ones – those only appear once the appropriate framework is installed.
这可能有效,也可能无效。但就最新版本而言,这应该是相当可靠的,因为旧版本(1.0、1.1)基本上有空文件夹,但没有新版本——只有在安装了适当的框架后才会出现。
Still, I suspect there must be a better way.
不过,我怀疑一定有更好的方法。

