在机器上返回.NET框架版本的PowerShell脚本是什么?
我的第一个猜测是与WMI有关。还有更好的办法吗?
它应该是一行程序,在每一行上只返回。net安装的最新版本。
在机器上返回.NET框架版本的PowerShell脚本是什么?
我的第一个猜测是与WMI有关。还有更好的办法吗?
它应该是一行程序,在每一行上只返回。net安装的最新版本。
当前回答
没有可靠的方法可以使用一个简单的脚本为所有平台和体系结构做到这一点。如果你想学习如何可靠地完成它,请从博客文章更新的。net框架检测代码样本开始,它可以进行更深入的检查。
其他回答
如果你要使用注册表,你必须递归才能得到完整版本的4。x框架。前面的答案都返回了。net 3.0系统上的根数(其中WCF和WPF的数字,嵌套在3.0下,更高——我无法解释),而4.0则没有返回任何东西……
编辑:对于。net 4.5及以上版本,这又发生了轻微的变化,所以现在有一篇很好的MSDN文章解释了如何将发布值转换为。net版本号,这完全是一场灾难:-(
这对我来说是正确的(注意它在3.0上为WCF和WPF输出单独的版本号。我不知道那是怎么回事)。它还输出客户端和完整的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-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
事实上,由于我必须不断更新这个答案,这里有一个脚本,从该网页的markdown源代码生成上面的脚本(带有一点额外的内容)。这可能会在某个时候崩溃,所以我保持上面的当前副本。
# 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 }}
"@
以下是我对这个问题的看法:
$gpParams = @{
Path = 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full'
ErrorAction = 'SilentlyContinue'
}
$release = Get-ItemProperty @gpParams | Select-Object -ExpandProperty Release
".NET Framework$(
switch ($release) {
({ $_ -ge 528040 }) { ' 4.8'; break }
({ $_ -ge 461808 }) { ' 4.7.2'; break }
({ $_ -ge 461308 }) { ' 4.7.1'; break }
({ $_ -ge 460798 }) { ' 4.7'; break }
({ $_ -ge 394802 }) { ' 4.6.2'; break }
({ $_ -ge 394254 }) { ' 4.6.1'; break }
({ $_ -ge 393295 }) { ' 4.6'; break }
({ $_ -ge 379893 }) { ' 4.5.2'; break }
({ $_ -ge 378675 }) { ' 4.5.1'; break }
({ $_ -ge 378389 }) { ' 4.5'; break }
default { ': 4.5+ not installed.' }
}
)"
这个例子适用于所有PowerShell版本,并且将永远工作,因为4.8是最后一个。net Framework版本。
请参阅“脚本”页,以查找远程工作站上安装的. net版本。
这里的脚本对于查找网络上多台机器的. net版本可能很有用。
好的解决方案
尝试使用可下载的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标准)由于不兼容…
“遗产”的动机功能如下
(你可以跳过阅读下面的代码)
We had to work with PS 2.0 on 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-DotnetLatestCompany and 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环境的函数(例如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
正确的语法:
[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