PowerShell 脚本返回机器上的 .NET Framework 版本?

Posted

技术标签:

【中文标题】PowerShell 脚本返回机器上的 .NET Framework 版本?【英文标题】:PowerShell script to return versions of .NET Framework on a machine? 【发布时间】:2010-08-15 12:02:02 【问题描述】:

在机器上返回 .NET Framework 版本的 PowerShell 脚本是什么?

我的第一个猜测是涉及 WMI。有更好的吗?

对于每次安装的 .NET [在每一行中],只返回最新版本应该是单行的。

【问题讨论】:

一台机器可以(并且将会)拥有多个版本的Fx。你想怎么处理?然后是 Fx2 .. Fx3.5SP1 混乱。你想听什么版本? 我想每次安装都需要返回完整的版本号。 有没有办法通过 WMI 做到这一点? 你要求 PowerShell,我为 C#(控制台应用程序)做了一些东西。如果您有兴趣,here 它是... 没有类似的东西真是不可思议:asp.net -v 【参考方案1】:

如果您要使用注册表,您必须递归才能获得 4.x 框架的完整版本。较早的答案都返回我系统上 .NET 3.0 的根编号(其中嵌套在 3.0 下的 WCF 和 WPF 编号更高——我无法解释),并且无法返回 4.0 的任何内容。 .

编辑:对于 .Net 4.5 及更高版本,这又略有变化,所以现在有一个很好的 MSDN article here 解释如何将 Release 值转换为 .Net 版本号,这是一个完整的火车沉船:-(

这在我看来是正确的(请注意,它在 3.0 上为 WCF 和 WPF 输出单独的版本号。我不知道那是什么意思)。它还在 4.0 上同时输出 ClientFull(如果您同时安装了它们):

Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -recurse |
Get-ItemProperty -name Version,Release -EA 0 |
Where  $_.PSChildName -match '^(?!S)\pL' |
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)\pL' |
  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)\pL' |
    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 
"@

【讨论】:

这正是我正在寻找的东西,但我很难弄清楚它到底在做什么。据我了解,它将进入 NDP 注册表并递归搜索适合 '^(?!S)\pL' 正则表达式的每个文件夹并获取版本和发布信息。该正则表达式究竟是什么试图限定? @Johnrad PSChildName 是注册表项的叶名称。 \pL 是 Unicode 类别“字母”中的任意字符。 (?!S) 是消极的环顾四周,^ 是字符串的开头。所以它必须以S 以外的字母开头。因此,如果您只考虑 ASCII,它与$_.PSChildName -cmatch '^[A-RT-Za-z]' 相同(注意-cmatch)。因此它会找到名称以S 以外的字母开头的键。如果您过滤掉以S 开头的名称,我不知道您为什么要关心非ASCII...肯定是因为您很困惑。 现在我对 Get-ItemProperty -name Version,Release -EA 0 到底在做什么感到更加困惑。我知道-EA 0-ErrorAction SilentlyContinue 相同,但是Get-ItemProperty -name Version,Release 在将所有结果传送给它时会产生什么影响?它似乎没有从对象中删除任何变量,因为其他变量在管道中的后续命令中使用。它是否运行,当键中缺少 VersionRelease 名称时出错,然后将它成功的对象传递到管道中的下一个命令? Get-ChildItem 返回所有注册表子项(如果您愿意的话,是子文件夹)。 Get-ItemProperty 返回值(特别是:“Version”和“Release”)——我们忽略错误,因为我们不关心没有这些值的文件夹。所以是的,基本上我们找到每个子文件夹,然后查找版本或发布(任何没有其中一个或两个的文件夹都会被忽略)。 太棒了!我只将(?!S) 子句修改为(?![SW]) 以进一步排除“Windows*”条目。这也可以通过(?=[vCF]) 完成,因为我们真正关心的唯一键是版本根以及 .NET 4.0+ 的“完整”和“客户端”键。 ;)【参考方案2】:

为脚本添加了 v4.8 支持:

Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -recurse |
Get-ItemProperty -name Version,Release -EA 0 |
Where  $_.PSChildName -match '^(?![SW])\pL' |
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" 
      
    

【讨论】:

【参考方案3】:
gci 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' |
sort pschildname -des                                  |
select -fi 1 -exp pschildname

如果已安装,此答案不会返回 4.5。以下来自@Jaykul 并使用递归的答案确实如此。

【讨论】:

gci 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' |排序 pschildname -des | foreach-object $_.name; $_.GetValue("版本"); 对我来说,答案现在是最重要的,所以这里有一个链接:-):***.com/a/3495491/1747983 在 Windows 10 上安装了 .NET 4.7.1,这仍然返回 v4.0。【参考方案4】:
[environment]::Version

为您提供当前 PSH 副本正在使用的 CLR 的 Version 实例(如文档中的 here 所述)。

【讨论】:

我安装了 .NET 4,但 PowerShell 只会使用 2.0 运行时。所以这在这里并没有真正的帮助。 @Johannes:看你对 Q 的评论,你需要明确你想要什么。 对于 Powershell 2.0,您还可以使用$PSVersionTable 查找运行 CLR PowerShell 的版本。 更高版本怎么样?我现在有 .NET 4.7.1,脚本总是返回 4.0.30319 Rev. 42000。 @Matt 您需要翻译版本的次要部分...并注意根据 Powershell 配置中设置的内容,它可能未使用最新的次要/补丁版本。【参考方案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   

【讨论】:

我在win8上试过这个,它什么也没返回。在 Windows 7 上,它返回 2 而 4.5.1 已经安装。我不知道为什么这在新平台上不可用。在 win sesrver 2008 上,它可以工作。 第一个选项适用于我的 Windows 8 64 位环境。第二个选项有效,但我认为这只是显示当前 PowerShell 实例正在运行的 .NET 版本,它几乎总是最新的。 (编辑:也许他们都这样做。) 这里也一样。在 Windows 7 上,我同时拥有 .net 2.0 和 4.0,但该命令仅显示 v2.0.50727。使用 Jaykul 的方法。 clr版本不等于framework版本,4+framework都是基于4个clr 更高版本怎么样?我现在有 .NET 4.7.1,脚本总是返回 4.0.30319 Rev. 42000。【参考方案6】:

我通过 osx 的 powershell 中的制表符完成找到了这个:

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

【讨论】:

是的,它返回 .NET Framework 4.7.2558.0 - 但是如何区分 4.7 和 4.7.1(我的 Windows 10 机器上有 4.7.1)。 [version]([Runtime.InteropServices.RuntimeInformation]::FrameworkDescription -replace '^.[^\d.]*','')【参考方案7】:

没有可靠的方法可以使用简单的脚本为所有平台和架构执行此操作。如果您想了解如何可靠地做到这一点,请从博文开始Updated sample .NET Framework detection code that does more in-depth checking

【讨论】:

【参考方案8】:

不错的解决方案

尝试使用可下载的DotNetVersionLister module(基于注册表信息和一些版本到营销版本的查找表)。

会这样使用:

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.0Win 7Win Server 2010 标准)...

以下“遗留”功能的动机

(您可以跳过阅读并使用下面的代码)

我们不得不在某些机器上使用 PS 2.0,无法安装/导入上述 DotNetVersionLister。 在我们想要更新(从 PS 2.0)到 PS 5.1(这又需要 .NET Framework >= 4.5)的其他机器上,使用两个公司自定义Install-DotnetLatestCompanyInstall-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://***.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://***.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)\pL' |
        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

【讨论】:

看不到时间使用(Get-DotNetVersion -LocalHost -nosummary)."&gt;=4.x" @ΩmegaMan:谢谢 - 在上面的答案中更新了你的好建议 :)【参考方案9】:

参考页面Script for finding which .NET versions are installed on remote workstations

那里的脚本可能有助于查找网络上多台机器的 .NET 版本。

【讨论】:

【参考方案10】:

不漂亮。 确实不漂亮:

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

这可能有效,也可能无效。但就最新版本而言,这应该是相当可靠的,因为旧版本(1.0、1.1)基本上有空文件夹,但新版本没有——这些只有在安装了适当的框架后才会出现。

不过,我怀疑一定有更好的方法。

【讨论】:

您需要再过滤一下,“V[.0-9]+”应该将匹配限制为 .NET 文件夹(我那里还有一些其他文件夹)。然后检查是否有真正的安装...安装组件上的 WMI 可能更容易。 嗯,对……在这台机器上还有一些其他文件夹——我的另一台机器上只有一堆其他文件。不过,整个答案更像是“为我工作”的案例。我确信有一种可靠且有意的方式来获取这些信息。 psake(构建自动化工具)采用了类似的方法并成功使用它(或者至少没有人因为问题而改变它)。但他们确实不需要完整的框架版本......对于我的电脑来说,这更接近:ls $Env:windir\Microsoft.NET\Framework | ? $_.PSIsContainer -and $_.Name -match '^v\d.[\d\.]+' | % $_.Name.TrimStart('v') 在答案中的所有单行代码中,由 stej 提供的最干净且按预期工作。如果是答案,我会投票给它。 不幸的是,它不可靠。我现在有 .NET 4.7.1,脚本总是 返回 v4.0.30319。【参考方案11】:

这是我在the msft documentation 之后对这个问题的看法:

$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 版本。

【讨论】:

【参考方案12】:

这纯粹是因为我不得不花时间制作/编辑它应该广泛使用的时候,所以我将它提供给其他人。

以下脚本将向 TEMP 输出几个 CSV 文件,其中包含选定(在代码中)OU 中每台机器的版本和漏洞状态。您将能够远程“安全审计”机器的 OU。

连接测试线需要Powershell 7.0 RSAT 需要获取 AD 模块 Visual Studio Code 需要获取 powershell 7.0(在 win7 上)

到您阅读本文时,文件中的版本列表可能已过期。使用此网站 https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/versions-and-dependencies 添加更新的 dotnet 条目。只是“DotNet4Builds”中的一堆关键值

如果在 CompromisedCheck.csv 中机器显示为 =0,则它的安全性已手动关闭,您应该指出是供应商这样做,还是可疑员工。

我希望这可以帮助搜索它的人搜索他们的业务。

     <#
        Script Name : Get-DotNetVersions_Tweaked.ps1
        Description : This script reports the various .NET Framework versions installed on the local or a remote set of computers
        Author      : Original by Martin Schvartzman - Edited by Mark Purnell
        Reference   : https://msdn.microsoft.com/en-us/library/hh925568
#>

$ErrorActionPreference = "Continue”
import-module ActiveDirectory
$searchOU = "OU=OU LEVEL 1,OU=OU LEVEL 2,OU=MACHINES,OU=OUR LAPTOPS,DC=PUT,DC=MY,DC=DOMAIN,DC=CONTROLLER,DC=HERE,DC=OK"
$computerList = Get-ADComputer -searchbase $searchOU -Filter *


function Get-DotNetFrameworkVersion($computerList)

    $dotNetter = @()
    $compromisedCheck = @()
    
    $dotNetRoot = 'SOFTWARE\Microsoft\.NETFramework'
    $dotNetRegistry  = 'SOFTWARE\Microsoft\NET Framework Setup\NDP'
    $dotNet4Registry = 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full'
    $dotNet4Builds = @
        '30319'  = @ Version = [System.Version]'4.0'                                                     
        '378389' = @ Version = [System.Version]'4.5'                                                     
        '378675' = @ Version = [System.Version]'4.5.1'   ; Comment = '(8.1/2012R2)'                      
        '378758' = @ Version = [System.Version]'4.5.1'   ; Comment = '(8/7 SP1/Vista SP2)'               
        '379893' = @ Version = [System.Version]'4.5.2'                                                   
        '380042' = @ Version = [System.Version]'4.5'     ; Comment = 'and later with KB3168275 rollup'   
        '393295' = @ Version = [System.Version]'4.6'     ; Comment = '(Windows 10)'                      
        '393297' = @ Version = [System.Version]'4.6'     ; Comment = '(NON Windows 10)'                  
        '394254' = @ Version = [System.Version]'4.6.1'   ; Comment = '(Windows 10)'                      
        '394271' = @ Version = [System.Version]'4.6.1'   ; Comment = '(NON Windows 10)'                  
        '394802' = @ Version = [System.Version]'4.6.2'   ; Comment = '(Windows 10 Anniversary Update)'   
        '394806' = @ Version = [System.Version]'4.6.2'   ; Comment = '(NON Windows 10)'                  
        '460798' = @ Version = [System.Version]'4.7'     ; Comment = '(Windows 10 Creators Update)'      
        '460805' = @ Version = [System.Version]'4.7'     ; Comment = '(NON Windows 10)'                  
        '461308' = @ Version = [System.Version]'4.7.1'   ; Comment = '(Windows 10 Fall Creators Update)' 
        '461310' = @ Version = [System.Version]'4.7.1'   ; Comment = '(NON Windows 10)'                  
        '461808' = @ Version = [System.Version]'4.7.2'   ; Comment = '(Windows 10 April & Winserver)'    
        '461814' = @ Version = [System.Version]'4.7.2'   ; Comment = '(NON Windows 10)'                  
        '528040' = @ Version = [System.Version]'4.8'     ; Comment = '(Windows 10 May 2019 Update)'  
        '528049' = @ Version = [System.Version]'4.8'     ; Comment = '(NON Windows 10)'  
    

    foreach($computerObject in $computerList)
    
        $computerName = $computerObject.DNSHostName
        write-host("PCName is " + $computerName)

        if(test-connection -TargetName $computerName -Quiet -TimeOutSeconds 1 -count 2)
            if($regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $computerName))           
            
                $os = (Get-WMIObject win32_operatingsystem -ComputerName SPL305350).Name
                if(!$?)
                    write-host("wim not available")
                    $dotNetter += New-Object -TypeName PSObject -Property @
                        'ComputerName' = $computerName
                        'OS' = "WIM not available"
                        'Build' = "WIM not available"
                        'Version' = "WIM not available"
                        'Comment' = "WIM not available"
                    
                
                else
                    if ($netRegKey = $regKey.OpenSubKey("$dotNetRegistry"))
                    
                        foreach ($versionKeyName in $netRegKey.GetSubKeyNames())
                        
                            if ($versionKeyName -match '^v[123]') 
                                $versionKey = $netRegKey.OpenSubKey($versionKeyName)
                                $version = [System.Version]($versionKey.GetValue('Version', ''))
                                
                                write-host("adding old dotnet")
                                $dotNetter += New-Object -TypeName PSObject -Property @
                                        ComputerName = $computerName
                                        OS = $os
                                        Build = $version.Build
                                        Version = $version
                                        Comment = ''
                                
                            
                        
                    
                    if ($net4RegKey = $regKey.OpenSubKey("$dotNet4Registry"))
                    
                        if(-not ($net4Release = $net4RegKey.GetValue('Release')))
                        
                            $net4Release = 30319
                        
                        
                        write-host("adding new dotnet")
                        $dotNetter += New-Object -TypeName PSObject -Property @
                                'ComputerName' = $computerName
                                'OS' = $os
                                'Build' = $net4Release
                                'Version' = $dotNet4Builds["$net4Release"].Version
                                'Comment' = $dotNet4Builds["$net4Release"].Comment
                        
                    
                    if ($netRegKey = $regKey.OpenSubKey("$dotNetRoot"))
                        write-host("Checking for hacked keys")
                        foreach ($versionKeyName in $netRegKey.GetSubKeyNames())
                        
                            if ($versionKeyName -match '^v[1234]') 
                                $versionKey = $netRegKey.OpenSubKey($versionKeyName)
                                write-host("versionKeyName is" + $versionKeyName)
                                write-host('ASPNetEnforceViewStateMac = ' + $versionKey.GetValue('ASPNetEnforceViewStateMac', ''))
                                $compromisedCheck += New-Object -TypeName PSObject -Property @
                                    'ComputerName' = $computerName
                                    'version' = $versionKeyName
                                    'compromisedCheck' = ('ASPNetEnforceViewStateMac = ' + $versionKey.GetValue('ASPNetEnforceViewStateMac', ''))
                                
                            
                        
                    
                
            
        
        else
            write-host("could not connect to machine")
            $dotNetter += New-Object -TypeName PSObject -Property @
                    'ComputerName' = $computerName
                    'OS' = $os
                    'Build' = "Could not connect"
                    'Version' = "Could not connect"
                    'Comment' = "Could not connect"
            
        
    
    $dotNetter | export-CSV c:\temp\DotNetVersions.csv
    $compromisedCheck | export-CSV C:\temp\CompromisedCheck.csv

get-dotnetframeworkversion($computerList)

【讨论】:

【参考方案13】:

大致思路如下:

在 .NET Framework 目录中获取名称匹配的容器的子项 模式v number dot number。按名称降序排列,取第一个对象, 并返回其 name 属性。

这是脚本:

(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

【讨论】:

我安装了 4.6.1 但你的脚本返回 v4.0.30319 这在我的机器上不起作用(我安装了 4.7.1)。它打印 v4.0.30319【参考方案14】:

我会在 PowerShell 中尝试这个: 为我工作!

(Get-ItemProperty "HKLM:Software\Microsoft\NET Framework Setup\NDP\v4\Full").Version

【讨论】:

这并没有告诉你真相。那里会说版本号,例如当产品版本为 4.7.2 时为 4.7.03056【参考方案15】:

如果您已在计算机上安装了 Visual Studio,则打开 Visual Studio 开发人员命令提示符并键入以下命令: 聪明的

它将列出该计算机上所有已安装的 .NET Framework 版本。

【讨论】:

此命令获取 CLR 版本,而不是 .NET Framework 版本 - 这是不同的。【参考方案16】:

我不了解我的 PowerShell 语法,但我认为您可以致电 System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion()。这会将版本作为字符串返回(我认为类似于 v2.0.50727)。

【讨论】:

对于当前执行的运行时,不一定是最新安装的。 对于 powershell,正确的语法是:[System.Runtime.InteropServices.RuntimeEnvironment]::GetSystemVersion(),但它只返回 v4.0.30319,即使在我的情况下安装了 v4.6。 @matt 4.0.30319 是从 .Net Framework 4.0 到 .Net Framework 4.7.1 的 CLR 版本。所以你的 v4.6 框架实际上使用 4.0.30319 作为它的 CLR 版本。请注意,只有版本的修订部分是所有 .Net 框架之间的差异。另请参阅:.NET Framework Versions and Dependencies - Microsoft Docs @walterlv - 谢谢你的链接。是的,我知道这一点。微软在这方面犯了一个大错误,远程连接到服务器并找出其中实际安装了哪个 .net 版本并不容易。另一个让管理员和开发人员头疼的问题。 这也可能有所帮助:Microsoft: How to determine versions and service pack levels of .NET Framework。它还显示了找出你的机器上究竟安装了什么变得多么复杂...... :-(【参考方案17】:

这是上一篇文章的派生,但在我的测试中获得了最新版本的 .net framework 4。

get-itemproperty -name version,release "hklm:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\FULL"

这将允许您调用远程机器的命令:

invoke-command -computername server01 -scriptblock get-itemproperty -name version,release "hklm:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\FULL" | select pscomputername,version,release 

使用 ADModule 和命名约定前缀设置了这种可能性:

get-adcomputer -Filter 'name -like "*prefix*"' | % invoke-command -computername $_.name -scriptblock get-itemproperty -name version,release "hklm:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\FULL" | select pscomputername,version,release | ft

【讨论】:

以上是关于PowerShell 脚本返回机器上的 .NET Framework 版本?的主要内容,如果未能解决你的问题,请参考以下文章

目标机器上的 TFS2015 Powershell

Powershell - 运行位于远程机器上的脚本,该脚本反过来从网络共享访问文件

用于查看当前登录用户(域和机器)+ 状态(活动、空闲、离开)的 Powershell 脚本

Powershell:如何使用不同的用户名/密码映射网络驱动器

检查是不是通过 Powershell 远程启用了 CredSSP

1-PowerShell 基本概念和用法