Keresés a tulajdonságok között (Search-Property)

Gyakran találkozunk olyan objektumokkal, amelyek nagyon sok tulajdonsággal rendelkeznek. Ilyenek például a WMI objektumok vagy az ActiveDirectory-ban található objektumok. A sok tulajdonság között nehéz észrevenni, hogy például melyekben található meg a számítógépünk neve vagy melyekben találhatók e-mailcím jellegű adatok. Készítsünk tehát egy olyan függvényt, ami segít nekünk a tulajdonságok közti keresésben!

Első próbálkozásként ezt raktam össze:

function Search-Property1 {

param(

    [string] $pattern = ".",

    [Parameter(ValueFromPipeline = $true)] $object

)

process{

    $object.psobject.properties |

        Where-Object {$_.name -match $pattern -or $_.value -match $pattern} |

            Select-Object -Property @{n="Object"; e={$object.tostring()}}, Name, Value

}

}

Két paraméterem van: $pattern az a minta, amit keresünk és a $object amiben keresünk. A $pattern alaphelyzet szerinti értéke „.”, ami azt jelenti, hogy csak azokat a tulajdonságokat kapom meg, amelyekben legalább 1 bármilyen karakter van. Az $object érkezhet a csövön keresztül is, így a függvényen belül a process blokkot kell alkalmazni.

Itt az $object tulajdonságain keresztül ($object.psobject.properties) egy Where-Object-tel szűröm, hogy melyek azok a tulajdonságok, ahol vagy a tulajdonság neve vagy az értéke illeszkedik a megadott mintára. Ha találok ilyet, akkor abból csinálok egy egyedi objektumot, ami első oszlopként tartalmazza magának az objektumnak a szöveggé konvertált változatát, majd a tulajdonság nevét és végül a tulajdonság értékét:

PS C:\> get-date | Search-Property1 -pattern Date

 

Object                 Name                                     Value

------                 ----                                     -----

2023. 01. 21. 13:44:45 DisplayHint                           DateTime

2023. 01. 21. 13:44:45 DateTime    2023. január 21., szombat 13:44:45

2023. 01. 21. 13:44:45 Date                     2023. 01. 21. 0:00:00

A fenti példában a Date mintára kerestem a get-date által kibocsátott objektumban. Látszik, hogy mind a tulajdonságok nevei között, mind az értékei között megtalálta a mintát.

Gyorsan bővítsük a függvényünket 3 kapcsoló paraméterrel!

function Search-Property2 {

param(

    [string] $pattern = ".",

    [Parameter(ValueFromPipeline = $true)] $object,

    [switch] $SearchInPropertyNames,

    [switch] $NotSearchInValues,

    [switch] $Literal

)

begin{

    if($Literal){

        $pattern = [regex]::Escape($pattern)

    }

}

process{

    $object.psobject.properties |

        Where-Object {($SearchInPropertyNames -and $_.name -match $pattern) -or (!$NotSearchInValues -and $_.value -match $pattern)} |

            Select-Object -Property @{n="Object"; e={$object.tostring()}}, Name, Value

}

}

A három kapcsoló közül az utolsó a $Literal. Ha ezt használjuk, akkor a begin blokkban átalakítom a mintát annak eszképelt változatára, azaz szó szerinti kereséseket tudok végrehajtani, nem pedig regex minta alapján. Az új változatban alapban a tulajdonságok neveiben nem keresünk, csak ha a $SearchInPropertyNames kapcsolót használjuk. Ha viszont pont csak a nevekben akarunk keresni, akkor a $NotSearchInValues kapcsolót használjuk. Ezeket a kapcsolókat integráltam a Where-Object feltételrendszerébe.

Az alábbi példában a szó szerinti „pöttyre” keresve alapban minden tulajdonságot megkapnék, viszont a ‑Literal kapcsolóval ezt kapom:

PS C:\> Get-Date | Search-Property2 -pattern "." -Literal

 

Object                 Name      Value                            

------                 ----      -----                            

2023. 01. 21. 18:11:13 DateTime  2023. január 21., szombat 18:11:13

2023. 01. 21. 18:11:13 TimeOfDay 18:11:13.0798403                 

Ha a „Date”-re keresünk, akkor más-más eredményt kapunk annak függvényében, hogy a és kapcsolókat használjuk:

PS C:\> Get-Date | Search-Property2 -pattern Date

 

Object                 Name           Value

------                 ----           -----

2023. 01. 21. 18:20:16 DisplayHint DateTime

 

 

PS C:\> Get-Date | Search-Property2 -pattern Date -SearchInPropertyNames

 

Object                 Name                                     Value

------                 ----                                     -----

2023. 01. 21. 18:20:20 DisplayHint                           DateTime

2023. 01. 21. 18:20:20 DateTime    2023. január 21., szombat 18:20:20

2023. 01. 21. 18:20:20 Date                     2023. 01. 21. 0:00:00

 

 

PS C:\> Get-Date | Search-Property2 -pattern Date -SearchInPropertyNames -NotSe

archInValues

 

Object                 Name     Value

------                 ----     -----

2023. 01. 21. 18:20:22 DateTime 2023. január 21., szombat 18:20:22

2023. 01. 21. 18:20:22 Date     2023. 01. 21. 0:00:00

Mivel lehetne még fejleszteni a függvényt? Például lehetne szűrni, hogy mely tulajdonságokban akarunk eleve keresni. Ezt két újabb paraméterrel tudjuk megadni, a $Property és az $ExcludeProperty szövegtömbökkel:

function Search-Property3 {

param(

    [string] $pattern = ".",

    [Parameter(ValueFromPipeline = $true)] $object,

    [switch] $SearchInPropertyNames,

    [switch] $NotSearchInValues,

    [switch] $Literal,

    [string[]] $Property = "*",

    [string[]] $ExcludeProperty

)

begin{

    if($Literal){

        $pattern = [regex]::Escape($pattern)

    }

}

process{

    $object.psobject.properties |

        Where-Object {

            $propname = $_.Name

            ($Property | Where-Object {$propname -like $_}) -and

            !($ExcludeProperty | Where-Object {$propname -like $_}) -and

            (($SearchInPropertyNames -and $_.name -match $pattern) -or (!$NotSearchInValues -and $_.value -match $pattern))

        } | Select-Object -Property @{n="Object"; e={$object.tostring()}}, Name, Value

}

}

Ezekkel a Where-Object feltételrendszerét kell kibővíteni. Mivel mindkét paraméter tömb, így két beágyazott Where-Object kifejezéssel kell vizsgálni, hogy az adott tulajdonságnév szerepel-e a kért tulajdonságok között ($Property) és nem szerepel a nem kértek között ($ExcludeProperty). Mivel kavarodás lenne a $_ használatából a kétszintű csővezetékeknél, így az aktuális tulajdonság nevét külön elmentem a $propname változóba. Mindkét paraméter esetében a -like operátorral vizsgálom az egyezést, így az ott használatos „*” és „?wildcard karaktereket használhatjuk. Nézzük a példákat:

PS C:\> Get-Date | Search-Property3 -pattern 2023

 

Object                 Name     Value

------                 ----     -----

2023. 01. 21. 18:52:11 DateTime 2023. január 21., szombat 18:52:11

2023. 01. 21. 18:52:11 Date     2023. 01. 21. 0:00:00

2023. 01. 21. 18:52:11 Year     2023

 

 

PS C:\> Get-Date | Search-Property3 -pattern 2023 -Property Date*

 

Object                 Name     Value

------                 ----     -----

2023. 01. 21. 18:52:27 DateTime 2023. január 21., szombat 18:52:27

2023. 01. 21. 18:52:27 Date     2023. 01. 21. 0:00:00

 

 

PS C:\> Get-Date | Search-Property3 -pattern 2023 -Property Date* -ExcludePrope

rty *Time

 

Object                 Name Value

------                 ---- -----

2023. 01. 21. 18:52:33 Date 2023. 01. 21. 0:00:00

Az első kifejezésben a „2023”-at tartalmazó tulajdonságokat kerestem, három találatot kaptam. A másodikban ezen belül csak a „Date”-tel kezdődőkre vagyok kíváncsi, itt már csak 2 találatom lett. Az utolsó kifejezésben a „Time” végűekre nem vagyok kíváncsi.

Mivel lehetne még gazdagítani a függvényt? Például azzal, hogy a mintánkban lehessen hivatkozni egy tulajdonság értékére. Például: keresem azokat a tulajdonságokat, amelyekben megtalálható az XY tulajdonságban tárolt érték. Nézzük példaként a Win32_ComputerSystem CIM objektumot:

PS C:\> Get-CimInstance -ClassName Cim_ComputerSystem | fl *

 

 

AdminPasswordStatus         : 0

BootupState                 : Normal boot

ChassisBootupState          : 3

KeyboardPasswordStatus      : 0

PowerOnPasswordStatus       : 0

PowerSupplyState            : 3

PowerState                  : 0

FrontPanelResetStatus       : 0

ThermalState                : 3

Status                      : OK

Name                        : STLENO

PowerManagementCapabilities :

PowerManagementSupported    :

Caption                     : STLENO

Description                 : AT/AT COMPATIBLE

Rengeteg tulajdonsága van, itt most csak az első néhányat másoltam ide. Látható, hogy a Name és Caption tulajdonság is tartalmazza a gépem nevét, de még több ilyen is van. Keresem az összes olyan tulajdonságot, ahol a Name tulajdonság értéke szerepel:

function Search-Property4 {

param(

    [string] $pattern = ".",

    [Parameter(ValueFromPipeline = $true)] $object,

    [switch] $SearchInPropertyNames,

    [switch] $NotSearchInValues,

    [switch] $Literal,

    [string[]] $Property = "*",

    [string[]] $ExcludeProperty

)

begin{

    if($Literal){

        $pattern = [regex]::Escape($pattern)

    }

    $origpattern = $pattern

}

process{

    if(!$LiteralSearch -and $origpattern  -match "<[^>]+>"){

        $pattern = [regex]::Replace($origpattern, "<([^>]+)>", {[regex]::Escape($object.($args[0].value -replace "<|>"))})

    }

   

    $object.psobject.properties |

        Where-Object {

            $propname = $_.Name

            ($Property | Where-Object {$propname -like $_}) -and

            !($ExcludeProperty | Where-Object {$propname -like $_}) -and

            (($SearchInPropertyNames -and $_.name -match $pattern) -or (!$NotSearchInValues -and $_.value -match $pattern))

        } | Select-Object -Property @{n="Object"; e={$object.tostring()}}, Name, Value

}

}

Ez a változat nem igényel újabb paramétert. Az eddigi $pattern paraméterben, ha egy „<tulajdonságnév>” kifejezést szerepeltetek (kacsacsőrök között a tulajdonság neve), akkor azt a függvény behelyettesíti a „tulajdonságnév” alatti tulajdonság értékével. Mivel így a minta dinamikusan kell, hogy változzon, ha több objektumot is betöltök a csőből, így el kell tároljam ez eredeti mintát a $origpattern változóba, ezt a begin részben teszem meg, majd egy jópofa regex kifejezéssel történik meg a dinamikus csere. Ezt láthattuk a „ 1.4.7.16 Csere .NET osztállyal ” fejezetben. Itt még annyi a trükk, hogy a dinamikus csere közben még egy [regex]::Escape metódust is meghívok.

Nézzük ezt használat közben:

PS C:\> Get-CimInstance -ClassName Cim_ComputerSystem | Search-Property4 -patte

rn "<Name>"

 

Object                                         Name                  Value

------                                         ----                  -----

Win32_ComputerSystem: STLENO (Name = "STLENO") Caption               STLENO

Win32_ComputerSystem: STLENO (Name = "STLENO") Name                  STLENO

Win32_ComputerSystem: STLENO (Name = "STLENO") DNSHostName           STLeno

Win32_ComputerSystem: STLENO (Name = "STLENO") UserName              STLeno...

Win32_ComputerSystem: STLENO (Name = "STLENO") CimInstanceProperties {Capti...

 

 

PS C:\> Get-CimInstance -ClassName Cim_ComputerSystem | Search-Property4 -patte

rn "^<Name>$"

 

Object                                         Name        Value

------                                         ----        -----

Win32_ComputerSystem: STLENO (Name = "STLENO") Caption     STLENO

Win32_ComputerSystem: STLENO (Name = "STLENO") Name        STLENO

Win32_ComputerSystem: STLENO (Name = "STLENO") DNSHostName STLeno

Az első esetben a Name tulajdonság értékét keresem, a találatokban az is szerepel, ahol a gépem neve, mint rész-sztring szerepel. A második példában csak teljes egyezést keresek.

Az utolsó előtti verzióban néhány esztétikai módosítást teszek még. Egyrészt képessé teszem a függvényt, hogy a több objektumot ne csak a csőből, hanem az $object paraméterbe tömbként is át lehessen adni. Ehhez a $object paraméter elé teszem a [PSObject[]] típusjelölőt, másrészt a processz blokkban egy foreach ciklussal megyek végig az elemeken és ennek megfelelően a cikluson belül a $o ciklusváltozóra hivatkozom:

function Search-Property5 {

param(

    [string] $pattern = ".",

    [Parameter(ValueFromPipeline = $true)] [PSObject[]] $object,

    [switch] $SearchInPropertyNames,

    [switch] $NotSearchInValues,

    [switch] $Literal,

    [string[]] $Property = "*",

    [string[]] $ExcludeProperty

)

begin{

    if($Literal){

        $pattern = [regex]::Escape($pattern)

    }

    $origpattern = $pattern

}

process{

    foreach($o in $object){

        if(!$LiteralSearch -and $origpattern  -match "<[^>]+>"){

            $pattern = [regex]::Replace($origpattern, "<([^>]+)>", {[regex]::Escape($o.($args[0].value -replace "<|>"))})

        }

   

        $o.psobject.properties |

            Where-Object {

                $propname = $_.Name

                ($Property | Where-Object {$propname -like $_}) -and

                !($ExcludeProperty | Where-Object {$propname -like $_}) -and

                (($SearchInPropertyNames -and $_.name -match $pattern) -or (!$NotSearchInValues -and $_.value -match $pattern))

            } | Select-Object -Property @{n="Object"; e={$o.tostring()}}, Name, Value

    }

}

}

Akkor erre is nézzünk néhány példát:

PS C:\> Get-ChildItem C:\PSTools\d* | Search-Property5 -pattern "<extension>"

 

Object                       Name        Value

------                       ----        -----

C:\PSTools\data-20230102.csv PSPath      Microsoft.PowerShell.Core\FileSyst...

C:\PSTools\data-20230102.csv PSChildName data-20230102.csv

C:\PSTools\data-20230102.csv VersionInfo File:             C:\PSTools\data-...

C:\PSTools\data-20230102.csv Name        data-20230102.csv

C:\PSTools\data-20230102.csv FullName    C:\PSTools\data-20230102.csv

C:\PSTools\data-20230102.csv Extension   .csv

C:\PSTools\dummy.ps1         PSPath      Microsoft.PowerShell.Core\FileSyst...

C:\PSTools\dummy.ps1         PSChildName dummy.ps1

C:\PSTools\dummy.ps1         VersionInfo File:             C:\PSTools\dummy...

C:\PSTools\dummy.ps1         Name        dummy.ps1

C:\PSTools\dummy.ps1         FullName    C:\PSTools\dummy.ps1

C:\PSTools\dummy.ps1         Extension   .ps1

 

 

PS C:\> $files = Get-ChildItem C:\PSTools\d*

PS C:\> Search-Property -object $files -pattern "<extension>"

 

Object                       Name        Value

------                       ----        -----

C:\PSTools\data-20230102.csv PSPath      Microsoft.PowerShell.Core\FileSyst...

C:\PSTools\data-20230102.csv PSChildName data-20230102.csv

C:\PSTools\data-20230102.csv VersionInfo File:             C:\PSTools\data-...

C:\PSTools\data-20230102.csv Name        data-20230102.csv

C:\PSTools\data-20230102.csv FullName    C:\PSTools\data-20230102.csv

C:\PSTools\data-20230102.csv Extension   .csv

C:\PSTools\dummy.ps1         PSPath      Microsoft.PowerShell.Core\FileSyst...

C:\PSTools\dummy.ps1         PSChildName dummy.ps1

C:\PSTools\dummy.ps1         VersionInfo File:             C:\PSTools\dummy...

C:\PSTools\dummy.ps1         Name        dummy.ps1

C:\PSTools\dummy.ps1         FullName    C:\PSTools\dummy.ps1

C:\PSTools\dummy.ps1         Extension   .ps1

Az első kifejezésben keresem a fájljaimnak azon tulajdonságait, ahol az extension tulajdonságuk értéke szerepel. Ezt itt a csövön keresztül hajtom végre. Az ezt követő példában ezeket a fájlokat előbb berakom a $files változóba, majd hagyományos módon adom át ezt a tömböt a $object paraméternek.

A végleges verzióban (két évvel később 😊) további fejlesztések történtek:

Tettem bele comment-based help-et.

Szebbé tettem a paraméter neveket (nagybetűvel kezdődnek).

Kis-nagybetű érzékenységet be lehet kapcsolni a -CaseSensitive kapcsolóval.

Az új -ObjectNameProp paraméterrel megadható, hogy melyik tulajdonság értéke kerüljön a végeredmény első oszlopába, ha a ToString() eredménye nem elég informatív.

Az -IgnoreCollection kapcsolóval kihagyhatjuk azokat a tulajdonságokat, ahol a tulajdonság értéke egy gyűjtemény.

A -Depth paraméterrel meghatározhatjuk, hogy milyen mélységben keressük a tulajdonságok között. A rekurzív végrehajtás megsegítésére néhány rejtett paramétert is használ a függvény: a $_Depth az aktuális mélységet, a $_ParentNames tartalmazza az aktuális tulajdonság-mélység elérési útját, az $_ObjectName pedig a kezdeti objektum nevét.

function Search-Property {

<#

.Synopsis

   Searches for patterns in properties of objects or keys of hashtables.

.DESCRIPTION

   This function primarily searches the regex pattern among properties of objects or keys of hashtables. If the -SearchInPropertyNames is specified then it searches among property names / keys as well.

   If the -ExcludeValues switch is used then it skips the search in values of properties / keys.

   If we want a literal search and not a regex pattern matching then the -LiteralSearch switch can be used. If we want to restrict search in certain properties / keys, then we can specify those names at the -Propery parameter.

   If the pattern is in the form of '<name>', the the function searches for all the properties / keys where the value matches the value of property / key with name 'name'.

   If we want to skip certain properties / keys, then we can specify those at the -ExcludeProperty parameter.

   By default the search is case insensitive, we can make it case sensitive by specifying the -CaseSensitive switch.

   By default the search is done among those properties / keys which contain a collection of values. To skip searching in those properties we can specify the -IgnoreCollections switch.

   By default the search goes into the immediate properties / keys of the input objects. We can specify the search depth by assigning a value to the -Depth parameter.

   The result contains custom objects having an 'Object' property which is meant to be an identifyer of the input objects. That is by default the result of the ToString() method invoking on the input object.

   If we want to have that identifier of one of the properties of the input object then we can specify that property name / key in the -ObjectNameProp parameter.

.EXAMPLE

   Get-Item -Path C:\Windows\notepad.exe | Search-Property -Pattern '<basename>' -Depth 2 -ObjectNameProp name -CaseSensitive -IgnoreCollections

 

   In this example we search the base name of the notepad.exe file object (notepad) among its properties and the properties of properties (-Depth 2) in a case sensitive way, so the VersionInfo.OriginalFilename property is not returned, because there the value is NOTEPAD.EXE.MUI.

   The first column of the result set contain the name of the file (notepad.exe) and not the full path, because we specified that the object name should be taken from property 'name'.

.EXAMPLE

   @{One = "MyValue"; KeyTwo = 'One'; Coll = 'one', 'two'; KeyThree = @{SubKey1 = 'One'; SubKey2 = [pscustomobject]@{Prop1 = 'One'; Prop2One = 'Text'}}} | Search-Property -Pattern '^One$' -SearchInPropertyNames -Depth 3 -IgnoreCollections

 

   In this example we search for the exact string 'One' among all the keys of the hashtable specified in the command line max 3 levels deep. We skip the key 'Coll', because that contains a collection and we specified the -IgnoreCollections switch. The result also contains property 'Prop1' of the object under the key 'Subkey2'.

.INPUTS

   hashtable or psobject

.OUTPUTS

   Collection of custom objects having an Object, Name and Value properties.

#>

param(

    # Regex pattern to search for      

    [parameter(Position=0)][string] $Pattern = ".",

 

    # Input object or hashtable

    [parameter(ValueFromPipeline)][psobject[]] $Object,

 

    # Extend the search to include property / key names

    [switch] $SearchInPropertyNames,

 

    # Skip searching among property / key values

    [switch] $ExcludeValues,

 

    # Use the pattern as a literal search (no regex metacharacters)

    [switch] $LiteralSearch,

 

    # Property / key names to search in (by default all all properties / keys are included)

    [string[]] $Property = "*",

 

    # Property / key names to exclude to search in

    [string[]] $ExcludeProperty,

 

    # Take the identifier of the object / hashtable from this property / key

    [string] $ObjectNameProp,

 

    # Make the search case-sensitive

    [switch] $CaseSensitive,

 

    # Ignore properties / keys that contain collection of values

    [switch] $IgnoreCollections,

 

    # Depth of the recursive search, by default 1 - shallow search

    [int] $Depth = 1,

    [Parameter(DontShow = $true)] [int] $_Depth = 1,

    [Parameter(DontShow = $true)] [string[]] $_ParentNames,

    [Parameter(DontShow = $true)] [string] $_ObjectName

)

begin{

    if($LiteralSearch -and $Pattern -ne "."){

        $Pattern = [regex]::Escape($Pattern)           

    }

 

    if($CaseSensitive){

        $Pattern = "(?-i)$Pattern"

    }

 

    $origpattern = $Pattern

}

process{

    foreach($o in $Object){

        if(!$o){

            continue

        }

 

        if($o -is [collections.ilist]){

            $index = 0

 

            foreach($elem in $o){

                $parentNames = "$_ParentNames[$index]"

 

                Search-Property -Object $elem -Pattern $origpattern -SearchInPropertyNames:$SearchInPropertyNames -ExcludeValues:$ExcludeValues -LiteralSearch:$LiteralSearch -Property:$Property -ExcludeProperty:$ExcludeProperty -CaseSensitive:$CaseSensitive -IgnoreCollections:$IgnoreCollections -Depth $Depth -_Depth ($_Depth + 1) -_ParentNames $parentNames -_ObjectName $_ObjectName

                $index++

            }

        }

        else{

            if(!$LiteralSearch -and $origpattern -match "<[^>]+>"){

                $Pattern = [regex]::Replace($origpattern, "<([^>]+)>", {[regex]::Escape($o.($args[0].value -replace "<|>"))})

            }

 

            if($o -is [System.Collections.Hashtable] -or $o -is [System.Collections.Specialized.OrderedDictionary]){

                $properties = $o.getenumerator() | Select-Object -Property Name, Value

            }

            else{

                $properties = $o.psobject.properties

            }

 

            if($_ObjectName){

                $objectName = $_ObjectName

            }

            elseif($ObjectNameProp){

                $objectName = $o.$ObjectNameProp

            }

            else{

                $objectName = $o.ToString()

            }

 

            foreach($prop in ($properties | Sort-Object -Property Name)){

                $PropName = $prop.Name

 

                if(

                    $prop.membertype -ne 'AliasProperty' -and

                    (

                        $(if(!$ExcludeValues){$prop.value -as [string] -and $prop.value -match $Pattern}) -or

                        $(if($SearchInPropertyNames){$prop.value -as [string] -and $prop.name -match $Pattern})

                    ) -and

                    !($ExcludeProperty | &{process {if($PropName -like $_){$_}}}) -and

                    ($Property | &{process {if($PropName -like $_){$_}}}) -and

                    (!$IgnoreCollections -or $prop.value -isnot [collections.ilist])

                ){

                    $propFullName = ($_ParentNames + $PropName) -join "."

                    Select-Object -InputObject $prop -Property @{n = "Object"; e = {$objectName}}, @{n = "Name"; e = {$propFullName}}, Value

                }

                   

                if($prop.value -and $prop.value.gettype().fullname -notin 'system.string', 'system.int32' -and $_Depth -lt $Depth){

                    if($prop.value -is [collections.ilist]){

                        Search-Property -Object (,$prop.value) -Pattern $pattern -SearchInPropertyNames:$SearchInPropertyNames -ExcludeValues:$ExcludeValues -LiteralSearch:$LiteralSearch -Property $Property -ExcludeProperty $ExcludeProperty -CaseSensitive:$CaseSensitive -IgnoreCollections:$IgnoreCollections -Depth $Depth -_Depth ($_Depth + 1) -_ParentNames ($_ParentNames + $PropName) -_ObjectName $objectName

                    }

                    else{

                        Search-Property -Object $prop.value -Pattern $pattern -SearchInPropertyNames:$SearchInPropertyNames -ExcludeValues:$ExcludeValues -LiteralSearch:$LiteralSearch -Property $Property -ExcludeProperty $ExcludeProperty -CaseSensitive:$CaseSensitive -IgnoreCollections:$IgnoreCollections -Depth $Depth -_Depth ($_Depth + 1) -_ParentNames ($_ParentNames + $PropName) -_ObjectName $objectName

                    }

                }

            }

        }

    }

}

}

Nézzünk pár példát:

PS C:\> @{Name = 'MyHashTable'; Coll = 'one', 'two'} | Search-Property -Pattern '^One$'

 

Object                       Name Value

------                       ---- -----

System.Collections.Hashtable Coll {one, two}

A keresés tárgya most egy olyan hashtábla, aminek egy Name és egy Coll kulcsa. A Coll egy gyűjteményt tartalmaz. Elsőre csak az a szót keresem, hogy ’One’. Az eredményben az Object oszlopban csak annyi szerepel, hogy az egy hashtábla. Az -ObjectNameProp paraméterrel ez lecserélhető a Name kulcs alatti értékre:

PS C:\> @{Name = 'MyHashTable'; Coll = 'one', 'two'} | Search-Property -Pattern '^One$' -ObjectNameProp Name

 

Object      Name Value

------      ---- -----

MyHashTable Coll {one, two}

Növelhetjük a keresés mélységét a -Depth paraméterrel:

PS C:\> @{Name = 'MyHashTable'; Coll = 'one', 'two'} | Search-Property -Pattern '^One$' -ObjectNameProp Name -Depth 2

 

Object      Name    Value

------      ----    -----

MyHashTable Coll    {one, two}

MyHashTable Coll[0] one

Látszik, hogy most 2 találatunk van: a Coll és a Coll[0]. Ha nem akarunk keresni a gyűjtemény típusú tulajdonságokban, akkor az -IgnoreCollections kapcsolót használjuk:

PS C:\> @{Name = 'MyHashTable'; Coll = 'one', 'two'} | Search-Property -Pattern '^One$' -ObjectNameProp Name -Depth 2 -IgnoreCollections

Ilyenkor persze nincs egy találatunk sem.



Word To HTML Converter