PowerShell 脚本在机器上返回 .NET Framework 的版本是什么?
我的第一个猜测是涉及 WMI。有更好的吗?
对于每个安装的 .NET [在每一行上],只返回最新版本应该是单行的。
asp.net -v
如果要使用注册表,则必须递归才能获得 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 }}
"@
为脚本添加了 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" }
}
}
}
gci 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' |
sort pschildname -des |
select -fi 1 -exp pschildname
如果已安装,此答案不会返回 4.5。以下来自@Jaykul 和使用递归的答案确实如此。
[environment]::Version
为您提供当前 PSH 副本正在使用的 CLR 的 Version
实例(如记录的 here)。
$PSVersionTable
查找运行 CLR PowerShell 的版本。
正确的语法:
[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
我通过 osx 的 powershell 中的选项卡完成发现了这一点:
[System.Runtime.InteropServices.RuntimeInformation]::get_FrameworkDescription() .NET Core 4.6.25009.03
[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
) .
[System.Runtime.InteropServices.RuntimeInformation]::FrameworkDescription
报告的字符串中提取版本信息:Rabash 的方法来自上述两条评论,适用于 .NET Framework。对于 .NET (Core),即来自 PowerShell (Core) v6+,将 [semver]
替换为 [version]
。
没有可靠的方法可以使用简单的脚本对所有平台和架构执行此操作。如果您想了解如何可靠地做到这一点,请从博文开始Updated sample .NET Framework detection code that does more in-depth checking。
不错的解决方案
尝试使用可下载的 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"
请参阅第 Script for finding which .NET versions are installed on remote workstations 页。
那里的脚本可能有助于查找网络上多台计算机的 .NET 版本。
不漂亮。绝对不漂亮:
ls $Env:windir\Microsoft.NET\Framework | ? { $_.PSIsContainer } | select -exp Name -l 1
这可能会也可能不会。但就最新版本而言,这应该是相当可靠的,因为旧版本(1.0、1.1)基本上有空文件夹,但新版本没有——这些只有在安装了适当的框架后才会出现。
不过,我怀疑一定有更好的方法。
ls $Env:windir\Microsoft.NET\Framework | ? { $_.PSIsContainer -and $_.Name -match '^v\d.[\d\.]+' } | % { $_.Name.TrimStart('v') }
以下是我在 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 版本。
这纯粹是因为我不得不花时间制作/编辑它应该被广泛使用,所以我将它提供给其他人。
下面的脚本将输出几个 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)
这是一般的想法:
获取 .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
我会在 PowerShell 中尝试这个:为我工作!
(Get-ItemProperty "HKLM:Software\Microsoft\NET Framework Setup\NDP\v4\Full").Version
如果您已在计算机上安装了 Visual Studio,则打开 Visual Studio 开发人员命令提示符并键入以下命令:clrver
它将列出该计算机上所有已安装的 .NET Framework 版本。
我不了解我的 PowerShell 语法,但我认为您可以调用 System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion()。这会将版本作为字符串返回(我认为类似于 v2.0.50727
)。
[System.Runtime.InteropServices.RuntimeEnvironment]::GetSystemVersion()
,但它只返回 v4.0.30319,即使在我的情况下安装了 v4.6。
这是上一篇文章的派生,但在我的测试中获得了最新版本的 .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
不定期副业成功案例分享
'^(?!S)\p{L}'
正则表达式的每个文件夹并获取版本和发布信息。该正则表达式究竟是什么试图限定?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
会产生什么影响?它似乎没有从对象中删除任何变量,因为其他变量在管道中的后续命令中使用。它是否运行,当键中缺少Version
或Release
名称时出错,然后将它成功的对象传递到管道中的下一个命令?(?!S)
子句修改为(?![SW])
以进一步排除“Windows*”条目。这也可以使用(?=[vCF])
完成,因为我们真正关心的唯一键是版本根以及 .NET 4.0+ 的“完整”和“客户端”键。 ;)