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.