ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

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

1
16 revs, 9 users 86%

如果要使用注册表,则必须递归才能获得 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 上同时输出 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

根据 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

事实上,由于我必须不断更新这个答案,这里有一个脚本,用于从该网页的降价源生成上面的脚本(有一点额外的)。这可能会在某个时候中断,所以我将当前副本保留在上面。

# 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 }}
"@

这也正是我正在寻找的东西,但我很难完全理解这到底在做什么。据我了解,它将进入 NDP 注册表并递归搜索适合 '^(?!S)\p{L}' 正则表达式的每个文件夹并获取版本和发布信息。该正则表达式究竟是什么试图限定?
@Johnrad PSChildName 是注册表项的叶名称。 \p{L} 是 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+ 的“完整”和“客户端”键。 ;)
J
Jaquez

为脚本添加了 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" }
      }
    }
}

P
Peter Mortensen
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 对象 {$_.name; $_.GetValue("版本");}
对我来说,答案现在是最重要的,所以这里有一个链接:-):stackoverflow.com/a/3495491/1747983
在 Windows 10 上安装了 .NET 4.7.1,这仍然返回 v4.0。
R
Richard
[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配置中设置的内容,它可能没有使用最新的次要/补丁版本。
I
Iain Samuel McLean Elder

正确的语法:

[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+frameworks都是基于4个clr
更高版本呢?我现在有 .NET 4.7.1,脚本总是返回 4.0.30319 Rev. 42000。
j
js2010

我通过 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.]*','')
澄清一下:静态 [System.Runtime.InteropServices.RuntimeInformation]::FrameworkDescription 属性在 .NET Framework v4.7.1+ 和所有 .NET (Core) 版本中都可用,因此在 Windows 上也可用。从 PowerShell 调用时,它反映了 PowerShell 会话底层的 .NET 框架版本。正如 Matt 指出的,在 Windows PowerShell 中,报告的版本号反映 .NET Framework 产品 版本号(例如 4.7.2) .
要获取 .NET Framework 产品 版本号,必须查阅注册表,例如 this answer 中所示。至于从 [System.Runtime.InteropServices.RuntimeInformation]::FrameworkDescription 报告的字符串中提取版本信息:Rabash 的方法来自上述两条评论,适用于 .NET Framework。对于 .NET (Core),即来自 PowerShell (Core) v6+,将 [semver] 替换为 [version]
P
Peter Mortensen

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


A
Andreas Covidiot

不错的解决方案

尝试使用可下载的 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.0(Win 7,Win Server 2010 标准)......

以下“遗留”功能的动机

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

我们不得不在某些机器上使用 PS 2.0,无法安装/导入上述 DotNetVersionLister
在我们想要更新的其他机器上(来自 PS 2.0)在两个公司自定义 Install-DotnetLatestCompany 和 {2 }.
为了更好地指导管理员完成安装/更新过程,我们必须在所有机器和现有 PS 版本上确定这些函数中的 .NET 版本。
因此,我们还使用以下函数来更安全地确定它们在所有环境中...

旧版 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

要看不到时间,请使用 (Get-DotNetVersion -LocalHost -nosummary).">=4.x"
@ΩmegaMan:谢谢-在上面的答案中更新了您的好建议:)
P
Peter Mortensen

请参阅第 Script for finding which .NET versions are installed on remote workstations 页。

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


J
Joey

不漂亮。绝对不漂亮:

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。
M
Maximilian Burszley

以下是我在 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 版本。


M
Mark Purnell

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

下面的脚本将输出几个 CSV 文件到 TEMP,其中包含选定(在代码中)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)

P
Peter Mortensen

这是一般的想法:

获取 .NET Framework 目录中的子项,这些子项是名称与模式 v number 点号匹配的容器。按名称降序对它们进行排序,获取第一个对象,并返回其名称属性。

这是脚本:

(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
G
G.B.

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

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


这并没有告诉你真相。那里会说版本号,例如当产品版本为 4.7.2 时为 4.7.03056
A
Abdul Rauf

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

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


此命令获取 CLR 版本,而不是 .NET Framework 版本 - 这是不同的。
A
Andry

我不了解我的 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。它还显示了找出您的机器上究竟安装了什么变得多么复杂...... :-(
k
karel

这是上一篇文章的派生,但在我的测试中获得了最新版本的 .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