当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 搜索复杂对象的属性

作者:精品下载站 日期:2024-12-14 08:11:52 浏览:13 分类:玩电脑

搜索复杂对象的属性


[玩转系统] 搜索复杂对象的属性

在使用 PowerShell 时,您可能遇到过具有大量属性的对象。在其中找到价值是相当具有挑战性的。最常见的是 WMI 对象和 Active Directory 对象等对象。我们如何找到包含特定字符串或字符串模式的所有属性?我们如何找到包含服务器名称的 WMI 对象的属性?哪些 AD 属性包含用户的姓氏?让我们组合一个 PowerShell 函数来帮助回答这些问题!

枚举对象的属性

初学者 PowerShell 脚本编写者首先学习的命令之一是 Get-Member。该命令向我们显示对象的成员,包括属性成员。尽管我们的函数可以很好地构建在它的基础上,但在这种情况下,让我们看一下另一种选择,即对象的“psobject.properties”隐藏属性。以下表达式列出了当前 PowerShell 进程对象的属性(为了更好的可读性,对结果进行了裁剪):

[玩转系统] 搜索复杂对象的属性

在这里,我们可以看到所有属性及其名称、类型和值。还有一些进一步的“属性的属性”,但我们需要关注这三个。如果我们查看属性的类型,我们可以注意到有一个“AliasProperty”类型。我们实际上并不需要这种属性,因为它们只是存储其他属性的冗余信息。

让我们创建一个表达式,列出包含字符串“Windows ”的 PowerShell 进程对象的属性:

[玩转系统] 搜索复杂对象的属性

创建搜索属性函数

由于我们已经有了一个基本的解决方案,因此我们将其放置在函数内并为其分配参数,即 -object 和 -模式。我们可以让我们的对象通过管道进行搜索,因此该函数应该接受管道输入。我们还需要一个 ForEach 循环,以便我们的函数也可以处理对象数组:

function Search-Property {
param(
   [parameter(ValueFromPipeline)][psobject[]] $object,
   [string] $pattern = "." 
) 
process{ 
   foreach($o in $object){ 
      $o.psobject.properties | 
         Where-Object { 
            $_.membertype -ne 'AliasProperty' -and 
            $_.value -match $pattern 
         } | Select-Object -Property @{n = "Object"; e = {$o.tostring()}}, Name, Value 
   } 
} 
}

结果使用包含输入对象的字符串表示形式的新列进行扩展,以便我们可以看到某个属性属于哪个对象。当我们输入多个对象时,这一点很重要。如果我们运行它,我们会得到期望的结果:

[玩转系统] 搜索复杂对象的属性

让功能更强大

只要付出一点努力,我们就可以让这个功能变得更好。首先,我们可能希望从结果集中排除某些属性。例如,在 AD 用户帐户的属性中搜索“姓氏”的出现次数时,我们只需要那些可以通过 Set-ADUser cmdlet 更新的属性。我们可能想要排除 distinguishedName 和 CN,因为我们需要另一个命令 Rename-ADObject 来更新它们。为了排除某些属性,我们引入 ‑ExcludeProperty 参数,该参数可以接受带有通配符的字符串数组。

我们可能还想限制要搜索的属性的范围。例如,我们只想在包含字符串“Name”的属性中搜索。让我们有一个 ‑Property 参数,它也可以接受带有通配符的字符串数组来定义要搜索的属性集。如果我们不使用它参数,默认为所有属性。

我们可能还想将搜索模式应用于属性名称。为此,我们可以使用 SearchInPropertyNames 开关参数。或者我们可能只想在属性名称中搜索,而不是在属性值中搜索,所以让我们也有一个 ‑ExcludeValues 开关参数。

如果我们不想使用正则表达式而是使用文字搜索,我们也可以使用 ‑LiteralSearch 开关参数。

这是改进的功能:

function Search-Property {
param(
   [parameter(ValueFromPipeline)][psobject[]] $object, 
   [string] $pattern = ".", 
   [switch] $SearchInPropertyNames, 
   [switch] $ExcludeValues, 
   [switch] $LiteralSearch, 
   [string[]] $Property = "*", 
   [string[]] $ExcludeProperty 
) 
begin{
   if($LiteralSearch -and $pattern -ne "."){
      $pattern = [regex]::Escape($pattern) 
   } 
} 
process{
   foreach($o in $object){ 
      $o.psobject.properties | 
         Where-Object { 
            $propname = $_.name 
            $_.membertype -ne 'AliasProperty' -and 
            ( 
               $(if(!$ExcludeValues){$_.value -match $pattern}) -or 
               $(if($SearchInPropertyNames){$_.name -match $pattern}) 
            ) -and 
            !($ExcludeProperty | Where-Object {$propname -like $_}) -and 
            ($Property | Where-Object {$propname -like $_}) 
         } | Select-Object -Property @{n = "Object"; e = {$o.tostring()}}, Name, Value 
   } 
} 
}

新函数只比原来的函数长几行,其要点保持不变,因此值得思考可能的、更复杂的场景,在这些场景中我们可以使用我们的函数并添加一些新功能。

这是正在运行的新功能。在第一个示例中,我们希望查看 Win32_OperatingSystem 和 Win32_ComputerSystem WMI 对象中包含字符串“DNS”或我们的计算机名称的属性。除此之外,我们要排除那些以 2 个下划线开头的属性,因为它们只是 WMI 架构的一部分:

[玩转系统] 搜索复杂对象的属性

在下一个例子中,我们回到原来的问题。让我们看看用户帐户中包含姓氏的 AD 用户属性,但排除 distinguishedName 和其他需要 Rename-ADObject cmdlet 来更新的名称:

[玩转系统] 搜索复杂对象的属性

接下来是什么?

当然,我们可以通过添加一些帮助、示例或参数解释来进一步改进功能。可能有一个功能可以动态搜索包含其他属性值的属性。例如,搜索包含实际用户姓氏的所有用户帐户的所有属性。

我们希望您学到了一些新东西 - 或者至少在您的 PowerShell 工具包中获得了一个新的方便工具。您对于如何改进这个功能有什么想法?

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯