Gyakran adódik olyan helyzet, hogy nem egy konkrét tulajdonságra akarunk keresni, hanem két hasonló objektumot akarunk összehasonlítani és feltárni a tulajdonságaik közti különbségeket. Ugyan létezik a Compare-Object cmdlet, de ez a nevével ellentétben nem objektumokat, hanem gyűjteményeket hasonlít össze. Kellene készíteni egy Compare-Property függvényt!
A nehézség abban rejlik, hogy hogy itt nem csak háromfajta eset lehetséges az összehasonlítás során (<=, ==, =>), hanem több is, ráadásul ezek nem is teljesen egyértelműek. Természetesen a két objektum azonos nevű tulajdonságai lehetnek egyformák (==) és jelöljük a nyilakkal (<=, =>) azt, ha csak az egyikben vagy csak a másikban van meg az adott tulajdonság. Viszont, ha mindkettőben megvan ugyanaz a tulajdonság, csak más az értékük, akkor azt jelölhetjük ezzel: <>.
Kezdjük tehát összerakni ezt az összehasonlító függvényt!
function Compare-Property1 {
param(
$referenceobject,
$differenceobject
)
$allprops = @()
$rp = @()
$dp = @()
$rs = "r:"
$ds = "d:"
if($referenceobject){
$rp = $referenceobject.psobject.Properties |
Select-Object -ExpandProperty Name
$allprops = @($rp)
$rs += $referenceobject.tostring()
}
if($differenceobject){
$dp = $differenceobject.psobject.Properties |
Select-Object -ExpandProperty Name
foreach($p in $dp){
if($allprops -notcontains $p){
$allprops += $p
}
}
$ds += $differenceobject.tostring()
}
foreach($p in ($allprops | Sort-Object)){
$ra = $referenceobject.$p
$da = $differenceobject.$p
$rtype = if($null -eq $ra){"NULL"}else{$ra.gettype().fullname}
$dtype = if($null -eq $da){"NULL"}else{$da.gettype().fullname}
if($null -eq $ra -and $null -ne $da){
$equal = "=>"
}
elseif($null -ne $ra -and $null -eq $da){
$equal = "<="
}
elseif($rtype -ne $dtype){
$equal = "<>"
}
elseif($ra -is [collections.ilist]){
if(Compare-Object -ReferenceObject $ra -DifferenceObject $da){
$equal = "<>"
}
else{
$equal = "=="
}
}
elseif($ra -is [collections.idictionary]){
$ra = @($ra.getenumerator())
$da = @($da.getenumerator())
if(Compare-Object -ReferenceObject $ra -DifferenceObject $da -Property Key, Value){
$equal = "<>"
}
else{
$equal = "=="
}
}
else{
$equal = if($ra -eq $da){"=="}else{"<>"}
}
[pscustomobject]@{
Property = $p
Equal = $equal
$rs = $ra
$ds = $da
}
}
}
Két paraméterünk van egyelőre, a $referenceobject és a $differenceobject. Az $allprops-ban gyűjtöm az összes tulajdonságnevet, az $rp-ben a referencia tulajdonságneveit, a $dp-ben a differenciáét. Miután a végeredményből egy táblázatot szeretnék, az egyik oszlopnévben a differencia objektumra akarok hivatkozni, ennek az oszlopnak a neve „r:”-al kezdődik, hasonlóan a másik „d:”-al, ezeket az $rs és $ds változókba rakom, amiket majd megtoldom az adott objektumok sztringesített változatával.
A tulajdonságnevek gyűjtögetése utáni foreach ciklusban végig megyek a sorba rakott összes tulajdonságon és kitalálom, hogy vajon az adott tulajdonságok értékei a két objektumban vajon milyen viszonyban vannak egymással a fenti négy lehetőség közül. Az egyformaság egyik döntő kérdése, hogy vajon egyforma típusúak-e a tulajdonság értékei? Mert ha nem, akkor nem is nagyon kell tovább vizsgálgatni őket, hanem az eredmény „<>” lesz. Így az egyes típusokat az $rtype és $dtype változókba beteszem, itt külön eset, ha valamelyik $null, hiszen a semminek nincs tulajdonsága, ezért erre én „NULL”-t teszek oda be.
Előtte még attól függően, hogy a referencia vagy differencia objektum üres-e generálom a $equal változóba a „=>” vagy „<=” nyilakat. A típusok különbözőségének vizsgálata után már a következő elseif ágban már elég a referencia objektum típusára kitételeket tenni, hiszen a másik objektum is, ha már idáig eljutottunk, akkor ugyanolyan. Ha tehát egyik objektum tömbszerű ([collections.ilist]), akkor a Compare‑Object-el határozhatom meg az egyformaságukat. Ha a Compare-Object-nek van kimenete, akkor az azt jelenti, hogy nem egyforma a kettő, ha nincs kimenet, akkor egyforma.
Hasonlóan ehhez, a következő elseif-ben, ha szótárszerűek ([collections.idictionary]) az objektumok, akkor előbb tömbbé alakítom a szótárakat a GetEnumerator() metódussal és utána már szintén a Compare-Object-el hasonlítom őket össze.
A legvégén már a sima -eq operátorral hasonlítom össze őket. Kimenetként egyedi objektumokat bocsátok ki, melynek első tulajdonsága maga a vizsgált tulajdonság neve ($p), majd az összehasonlítás eredménye ($equal), majd a referencia objektum, végül a differencia objektum adott tulajdonságának értéke.
Nézzük meg működés közben is a függvényt! Ehhez kreálok két egyéni objektumot, amely rendelkezik mindenféle típusú tulajdonsággal:
$o1 = [pscustomobject]@{
értékegyforma = 1
értékkülönböző = "bla"
hashegyforma
= @{
key1 = "bla"
Key2 = "BlaBla"
}
hashkülönböző = @{
keyegy = 1
keykettő = 2
}
tömbegyforma
= 1,2,3
tömbkülönböző = 'a', 'b'
kétfajtasemmi = ""
semmi = $null
csakitt = "szöveg"
}
$o2 = [pscustomobject]@{
értékegyforma = 1
értékkülönböző = "kakukk"
hashegyforma
= @{
key1 = "bla"
Key2 = "BlaBla"
}
hashkülönböző = @{
keyegy = 5
keyhárom
= 3
}
tömbegyforma
= 1,2,3
tömbkülönböző = 'c', 'b'
kétfajtasemmi = @()
semmi = $null
}
Van itt minden, mint a búcsúban! Egyforma és különböző érték típusú tulajdonság, egyforma és különböző hashtábla, egyforma és különböző tömb, különböző és egyforma „semmi” és végül egy olyan tulajdonság, ami csak a referencia objektumban van. Ezeket összehasonlítva ezt kapjuk:
PS C:\> Compare-Property1 -referenceobject $o1 -differenceobject $o2
Property Equal r: d:
-------- ----- -- --
csakitt <= szöveg
értékegyforma == 1 1
értékkülönböző <> bla kakukk
hashegyforma == {key1, Key2} {key1, Key2}
hashkülönböző <> {keykettő, keyegy} {keyegy, keyhárom}
kétfajtasemmi <> {}
semmi ==
tömbegyforma == {1, 2, 3} {1, 2, 3}
tömbkülönböző <> {a, b} {c, b}
Az eredmény a várakozásunknak megfelelő lett! Mivel lehetne ezt még továbbfejleszteni? Vegyünk fel további paramétereket, amelyekkel lehet szűrni az eredményeket:
$includeequal : alapban az egyformákat nem jelenítjük meg, csak ha ezt a kapcsolót használjuk
$excludedifferent : alapban a különbözőket jelenítjük meg, de ezzel a kapcsolóval elrejthetjük azokat
$property : csak mely tulajdonságok között keressen
$exclude : mely tulajdonságokat hagyjon ki
Különösebben nem is magyarázom a 2. verziót, nézzük a függvényt:
function Compare-Property2 {
param(
$referenceobject,
$differenceobject,
[switch] $includeequal,
[switch] $excludedifferent,
[string[]] $property = "*",
[string[]] $exclude
)
$allprops = @()
$rp = @()
$dp = @()
$rs = "r:"
$ds = "d:"
if($referenceobject){
$rp = $referenceobject.psobject.Properties |
Select-Object -ExpandProperty Name
$allprops = @($rp)
$rs += $referenceobject.tostring()
}
if($differenceobject){
$dp = $differenceobject.psobject.Properties |
Select-Object -ExpandProperty Name
foreach($p in $dp){
if($allprops -notcontains $p){
$allprops += $p
}
}
$ds += $differenceobject.tostring()
}
$allprops = $allprops | Where-Object {
$pp = $_
($property | Where-Object {$pp -like $_}) -and !($exclude | Where-Object {$pp -like $_})
} | Sort-Object
foreach($p in ($allprops | Sort-Object)){
$ra = $referenceobject.$p
$da = $differenceobject.$p
$rtype = if($null -eq $ra){"NULL"}else{$ra.gettype().fullname}
$dtype = if($null -eq $da){"NULL"}else{$da.gettype().fullname}
if($null -eq $ra -and $null -ne $da){
$equal = "=>"
}
elseif($null -ne $ra -and $null -eq $da){
$equal = "<="
}
elseif($rtype -ne $dtype){
$equal = "<>"
}
elseif($ra -is [collections.ilist]){
if(Compare-Object -ReferenceObject $ra -DifferenceObject $da){
$equal = "<>"
}
else{
$equal = "=="
}
}
elseif($ra -is [collections.idictionary]){
$ra = @($ra.getenumerator())
$da = @($da.getenumerator())
if(Compare-Object -ReferenceObject $ra -DifferenceObject $da -Property Key, Value){
$equal = "<>"
}
else{
$equal = "=="
}
}
else{
$equal = if($ra -eq $da){"=="}else{"<>"}
}
if((!$excludedifferent -and $equal -ne '==') -or ($includeequal -and $equal -eq '==')){
[pscustomobject] @{
Property = $p
Equal = $equal
$rs = $referenceobject.$p
$ds = $differenceobject.$p
}
}
}
}
Nézzük, ez hogyan működik:
PS C:\>
Compare-Property2 -referenceobject $o1 -differenceobject $o2
Property Equal r: d:
-------- ----- -- --
csakitt <=
szöveg
értékkülönböző
<> bla kakukk
hashkülönböző <>
{keykettő, keyegy} {keyegy, keyhárom}
kétfajtasemmi <> {}
tömbkülönböző <>
{a, b} {c, b}
Ebben a 2. verzióban tehát alapban csak a különbözőségek látszanak, vegyük hozzá az egyformákat is:
PS C:\> Compare-Property2 -referenceobject $o1 -differenceobject $o2 -inc
ludeequal
Property Equal r: d:
-------- ----- -- --
csakitt <= szöveg
értékegyforma == 1 1
értékkülönböző <> bla kakukk
hashegyforma == {key1, Key2} {key1, Key2}
hashkülönböző <> {keykettő, keyegy} {keyegy, keyhárom}
kétfajtasemmi <> {}
semmi ==
tömbegyforma == {1, 2, 3} {1, 2, 3}
tömbkülönböző <> {a, b} {c, b}
Szűkítsük le az eredményeket az „é” vagy „t” betűkkel kezdődő tulajdonságokra, de azért a dupla „k” betűt tartalmazókat vegyük ki:
PS C:\> Compare-Property2 -referenceobject $o1 -differenceobject $o2 -inc
ludeequal -property é*, t* -exclude *kk*
Property Equal r: d:
-------- ----- -- --
értékegyforma == 1 1
tömbegyforma == {1, 2, 3} {1, 2, 3}
tömbkülönböző <> {a, b} {c, b}
A harmadik verzióban vezessünk be egy újabb szűrési lehetőséget, ahol elrejtjük a „semmit” tartalmazó sorokat. Semmi szerepelhet az egyik objektumnál, vagy mindkettőnél, vegy lehet olyan is, hogy pont a semmiket tartalmazó sorokat akarjuk megjeleníteni. Itt a „semmi” nem csak a tényleges $null-t, hanem az üres sztringet, üres tömböt, üres hashtáblát és a [system.dbnull]-t is jelentheti. Azaz az új paraméter legyen az, hogy $hide, ennek lehetséges értékei lehetnek: 'None', 'Empty', 'NonEmpty', 'BothEmpty', alapban az értéke ’None’, azaz nem rejtünk el semmit. Ezt a kiterjesztett „semmit” ki kell számolni, úgyhogy a függvényünk ezekkel a részekkel bővül, plusz még kiszűröm az AliasProperty típusú tulajdonságokat, valamint a „=>” és „<=” eredményeket rendelem azokhoz az esetekhez, ahol az egyik tulajdonság ezen kiterjesztett „semmi”, de a másik nem az:
function Compare-Property3 {
param(
$referenceobject,
$differenceobject,
[switch] $includeequal,
[switch] $excludedifferent,
[string[]] $property = "*",
[string[]] $exclude,
[ValidateSet('None','Empty','NonEmpty','BothEmpty')] $hide = 'None'
)
$allprops = @()
$rp = @()
$dp = @()
$rs = 'r:'
$ds = 'd:'
if($null -ne $referenceobject){
$rp = $referenceobject.psobject.Properties |
Where-Object {$_.membertype -ne 'AliasProperty'} |
Select-Object -ExpandProperty Name
$allprops = @($rp)
$rs = "r:" + $referenceobject.tostring()
}
if($null -ne $differenceobject){
$dp = $differenceobject.psobject.Properties |
Where-Object {$_.membertype -ne 'AliasProperty'} |
Select-Object -ExpandProperty Name
foreach($p in $dp){
if($allprops -notcontains $p){
$allprops += $p
}
}
$ds = "d:" + $differenceobject.tostring()
}
$allprops = $allprops | Where-Object {
$pp = $_
($property | Where-Object {$pp -like $_}) -and !($exclude | Where-Object {$pp -like $_})
} | Sort-Object
foreach($p in $allprops){
$ra = $referenceobject.$p
$da = $differenceobject.$p
$raempty = $null -eq $ra -or
'' -eq $ra -or
(($ra -is [collections.ilist] -or $ra -is [Collections.IDictionary]) -and $ra.count -eq 0) -or
$ra -is [System.DBNull]
$daempty = $null -eq $da -or
'' -eq $da -or
(($da -is [collections.ilist] -or $da -is [Collections.IDictionary]) -and $da.count -eq 0) -or
$ra -is [System.DBNull]
$rtype = if($null -eq $ra){"NULL"}else{$ra.gettype().fullname}
$dtype = if($null -eq $da){"NULL"}else{$da.gettype().fullname}
if($hide -eq 'Empty' -and ($raempty -or $daempty)){
continue
}
elseif($hide -eq 'BothEmpty' -and $raempty -and $daempty){
continue
}
elseif($hide -eq 'NonEmpty' -and (!$raempty -or !$daempty)){
continue
}
if(($raempty -and !$daempty) -or ($dp -contains $p -and $rp -notcontains $p)){
$equal = "=>"
}
elseif((!$raempty -and $daempty) -or ($rp -contains $p -and $dp -notcontains $p)){
$equal = "<="
}
elseif($rtype -ne $dtype){
$equal = "<>"
}
elseif($ra -is [collections.ilist]){
if(Compare-Object -ReferenceObject $ra -DifferenceObject $da){
$equal = "=="
}
else{
$equal = "<>"
}
}
elseif($ra -is [collections.idictionary]){
$ra = @($ra.GetEnumerator())
$da = @($da.GetEnumerator())
if(Compare-Object -ReferenceObject $ra -DifferenceObject $da -Property Key, Value){
$equal = "<>"
}
else{
$equal = "=="
}
}
else{
$equal = if($ra -eq $da){"=="}else{"<>"}
}
if((!$excludedifferent -and $equal -ne '==') -or ($includeequal -and $equal -eq '==')){
[pscustomobject] @{
Property = $p
Equal = $equal
$rs = $referenceobject.$p
$ds = $differenceobject.$p
}
}
}
}
És akkor nézzünk néhány példát ennek a paraméternek a használatára is:
PS C:\> Compare-Property3 -referenceobject $o1 -differenceobject $o2 -incl
udeequal -hide Empty
Property Equal r: d:
-------- ----- -- --
értékegyforma == 1 1
értékkülönböző <> bla kakukk
hashegyforma == {key1, Key2} {key1, Key2}
hashkülönböző <> {keykettő, keyegy} {keyegy, keyhárom}
tömbegyforma <> {1, 2, 3} {1, 2, 3}
tömbkülönböző == {a, b} {c, b}
Itt a „-hide Empty” opciót választottam, és így az eredményből ki is maradtak azok a sorok, ahol az egyik vagy másik tulajdonság „semmi” volt. A következő példában meg pont azokat rejtem el, ahol egyik sem „semmi”:
PS C:\> Compare-Property3 -referenceobject $o1 -differenceobject $o2 -incl
udeequal -hide NonEmpty
Property Equal r: d:
-------- ----- -- --
kétfajtasemmi <> {}
semmi ==
Az utolsó verzió - szintén 2 év múlva - a következő:
function Compare-Property {
<#
.Synopsis
Compares
properties of objects or keys of hashtables.
.DESCRIPTION
This function
compares properties of two objects or keys of two hashtables recursively and
returns a set of custom objects describing the differences.
.EXAMPLE
$f1 =
Get-Item C:\Windows\notepad.exe; $f2 = Get-Item
C:\Windows\System32\notepad.exe; Compare-Property -ReferenceObject $f1
-DifferenceObject $f2
This
expression compares the properties of 2 notepad.exe files and returns all
properties that are different.
.EXAMPLE
$f1 =
Get-Item C:\Windows\notepad.exe; $f2 = Get-Item
C:\Windows\System32\notepad.exe; Compare-Property -ReferenceObject $f1
-DifferenceObject $f2 -IncludeEqual -ExcludeDifferent -Exclude PS*
In this
example we compare the properties of the two notepad.exe file objects, exclude
the properties that are different but include properties that are equal. We
also exclude all properties whose name start with PS.
.EXAMPLE
Compare-Property -ReferenceObject @{Name = 'First'; Number = 1; Array =
1,2; RefEmpty = $null} -DifferenceObject @{Name = 'Second'; Number = 2; Array =
2,3; DiffEmpty = @()} -Hide Empty -NameProperty Name -Exclude Name
In this
example we compare the keys of two hashtables. We exclude those properties that
contain 'empty' values ($null, empty array, empty hashtables, System.DBNull) in
either input objects.
We also
include in the column names the content of the Name property of the respective
hashtables, but exclude the Name property from the differences.
.INPUTS
hashtable or
psobject
.OUTPUTS
Collection of
custom objects having a Property, Relation and 'r:<reference object ID>',
'd:<difference object ID>' properties.
#>
[cmdletbinding()]
param(
# The reference
object or hashtable
[Parameter(Mandatory
=
$true)]
[AllowNull()][psobject]
$ReferenceObject,
# The difference
object or hashtable
[Parameter(Mandatory
=
$true)]
[AllowNull()][psobject]
$DifferenceObject,
# Include equal
properties/keys in the result
[switch]
$IncludeEqual,
# Exclud differences
from the result
[switch]
$ExcludeDifferent,
# Include
properties/keys to compare
[string[]]
$Property
=
"*",
# Exclude
properties/keys to compare
[string[]]
$Exclude,
# Use this property
or the result of executing the scriptblock as the name for the objects
[ValidateScript({$_
-is
[string]
-or
$_
-is
[scriptblock]})]
[psobject]
$NameProperty,
# Hide certain type
of empty properties
[string]
[ValidateSet('None','Empty','NonEmpty','BothEmpty')]
$Hide
=
'None',
[Parameter(Dontshow
=
$true)][int]
$_Depth
=
1,
# Maximum depth of
recursion, default is 5
[int]
$MaxDepth
=
5
)
$equal
=
$null
$rObjName
=
''
$dObjName
=
''
if($null
-eq
$ReferenceObject
-and
$null
-eq
$DifferenceObject){
$rObjName
=
'$null'
$dObjName
=
'$null'
$equal
=
"=="
}
elseif($null
-eq
$ReferenceObject
-or
$null
-eq
$DifferenceObject){
if($null
-eq
$ReferenceObject){
$rObjName
=
'$null'
$equal
=
"=>"
}
else{
$dObjName
=
'$null'
$equal
=
"<="
}
}
elseif($ReferenceObject.GetType().FullName
-ne
$DifferenceObject.GetType().FullName
-and
$PSBoundParameters.ContainsKey('_Depth')){
$equal
=
"<>"
}
elseif($ReferenceObject
-is
[scriptblock]
-and
$PSBoundParameters.ContainsKey('_Depth')){
if($ReferenceObject.ToString()
-eq
$DifferenceObject.tostring()){
$equal
=
"=="
}
else{
$equal
=
"<>"
}
}
elseif($ReferenceObject
-is
[datetime]
-and
$PSBoundParameters.ContainsKey('_Depth')){
if($ReferenceObject
-eq
$DifferenceObject){
$equal
=
"=="
}
else{
$equal
=
"<>"
}
}
elseif($ReferenceObject.gettype().fullname
-in
'System.RuntimeType',
'System.Reflection.RuntimeAssembly'){
return
}
elseif($ReferenceObject
-is
[System.IO.FileSystemInfo]
-and
$PSBoundParameters.ContainsKey('_Depth')){
if($ReferenceObject.fullname
-eq
$DifferenceObject.fullname){
$equal
=
"=="
}
else{
$equal
=
"<>"
}
}
elseif($ReferenceObject
-is
[string]){
if($ReferenceObject
-eq
$DifferenceObject){
$equal
=
"=="
}
else{
$equal
=
"<>"
}
}
elseif($ReferenceObject
-as
[double]
-and
$DifferenceObject
-as
[double]){
if($ReferenceObject
-eq
$DifferenceObject){
$equal
=
"=="
}
else{
$equal
=
"<>"
}
}
elseif($ReferenceObject
-is
[system.collections.ilist]){
if($ReferenceObject.psbase.count
-ne
$DifferenceObject.psbase.count){
$equal
=
"<>"
}
else{
$equal
=
"=="
for($i
=
0;
$i
-lt
$ReferenceObject.psbase.count;
$i++){
$diff =
Compare-Property
-ReferenceObject
$ReferenceObject[$i]
-DifferenceObject
$DifferenceObject[$i]
-_Depth
($_Depth
+
1)
if($diff){
$equal =
"<>"
break
}
}
}
}
if($NameProperty){
if($NameProperty
-is
[string]){
if(!$rObjName){
$rObjName =
$ReferenceObject.$NameProperty
}
if(!$dObjName){
$dObjName =
$DifferenceObject.$NameProperty
}
}
else{
if(!$rObjName){
$rObjName =
$ReferenceObject
|
&{process{
&
$NameProperty}}
}
if(!$dObjName){
$dObjName =
$DifferenceObject
|
&{process{
&
$NameProperty}}
}
}
}
else{
if(!$rObjName){
$rObjName
=
$ReferenceObject.tostring()
}
if(!$dObjName){
$dObjName
=
$DifferenceObject.tostring()
}
}
$rs
=
"r:"
+
$rObjName
$ds
=
"d:"
+
$dObjName
if(!$equal
-and
$MaxDepth
-lt
$_Depth){
if($ReferenceObject.tostring()
-eq
$DifferenceObject.ToString()){
$equal
=
"=="
}
else{
$equal
=
"<>"
}
}
if($equal){
if($equal
-ne
'=='){
[pscustomobject]
@{
Property =
"<value>"
Relation =
$equal
$rs =
$ReferenceObject
$ds =
$DifferenceObject
}
}
}
else{
if($ReferenceObject
-is
[hashtable]
-or
$ReferenceObject
-is
[System.Collections.Specialized.OrderedDictionary]){
$ReferenceObject
=
[pscustomobject]
$ReferenceObject
$DifferenceObject
=
[pscustomobject]
$DifferenceObject
}
if($NameProperty){
if($NameProperty
-is
[string]){
$rObjName =
$ReferenceObject.$NameProperty
$dObjName =
$DifferenceObject.$NameProperty
}
else{
$rObjName =
$ReferenceObject
|
&{process{
&
$NameProperty}}
$dObjName =
$DifferenceObject
|
&{process{
&
$NameProperty}}
}
}
else{
$rObjName
=
$ReferenceObject.tostring()
$dObjName
=
$DifferenceObject.tostring()
}
$rs
=
"r:"
+
$rObjName
$ds
=
"d:"
+
$dObjName
$rp
=
$referenceobject.psobject.Properties
|
&{process{
if($_.membertype
-ne
'AliasProperty'){$_}}}
|
Select-Object
-ExpandProperty
Name
$allprops
=
@($rp)
$dp
=
$differenceobject.psobject.Properties
|
&{process
{if($_.membertype
-ne
'AliasProperty'){$_}}}
|
Select-Object
-ExpandProperty
Name
foreach($p
in
$dp){
if($allprops
-notcontains
$p){
$allprops +=
$p
}
}
$allprops
=
$allprops
|
&{process
{
$pp =
$_
if(($Property
|
&{process
{if($pp
-like
$_){$_}}})
-and
!($Exclude
|
&{process{if($pp
-like
$_){$_}}}))
{$_}
}} |
Sort-Object
foreach($p
in
$allprops){
if($rp
-contains
$p
-and
$dp
-contains
$p){
$ra =
$ReferenceObject.$p
$da =
$DifferenceObject.$p
$diff =
Compare-Property
-ReferenceObject
$ra
-DifferenceObject
$da
-Property
$Property
-Exclude
$Exclude
-_Depth
($_Depth
+
1)
if($diff){
$equal =
"<>"
}
else{
$equal =
"=="
}
}
elseif($rp
-contains
$p){
$equal =
"<="
$ra =
$ReferenceObject.$p
$da =
$null
}
else{
$equal =
"=>"
$da =
$DifferenceObject.$p
$ra =
$null
}
$raempty
=
$null
-eq
$ra
-or
''
-eq
$ra
-or
(($ra
-is
[collections.ilist]
-or
$ra
-is
[Collections.IDictionary])
-and
$ra.count
-eq
0)
-or
$ra
-is
[System.DBNull]
$daempty
=
$null
-eq
$da
-or
''
-eq
$da
-or
(($da
-is
[collections.ilist]
-or
$da
-is
[Collections.IDictionary])
-and
$da.count
-eq
0)
-or
$ra
-is
[System.DBNull]
if((!$Excludedifferent
-and
$equal
-ne
'==')
-or
($includeequal
-and
$equal
-eq
'==')){
$dummy =
0
if(($Hide
-eq
'BothEmpty'
-and
$raempty
-and
$daempty)
-or
($Hide -eq
'Empty'
-and
($raempty
-or
$daempty))
-or
($Hide -eq
'NonEmpty'
-and
(!$raempty
-or
!$daempty))){
continue
}
[pscustomobject]
@{
Property =
$p
Relation =
$equal
$rs =
$ra
$ds =
$da
}
}
}
}
}
Ebben a verzióban a következő változtatások történtek:
Az összehasonítás 2 hashtábla esetén is működik úgy, mintha a kulcsok tulajdonságok lennének.
Ha két összehasonlítandó tulajdonság szintén objektum, akkor az összehasonlítás rekurzívan történik erre a két tulajdonságra maximum -MaxDepth szintig. Ehhez bekerült egy rejtett paraméter $_Depth a rekurzió mélységének nyilvántartására.
Scriptblock típusú objektumok összehasonlításánál egyszerűen a sztring reprezenációjukat hasonlítom össze.
Fájlrendszer objektumot tartalmazó tulajdonságok összehasonlításánál a
FullName tulajdonságok kerülnek összehasonlításra.
Dátum-időt tartalmazó tulajdonságok összehasonlításánál ezek közvetlenül lesznek összehasonlítva, nem rekurzívan.
A Where-Object cmdleteket lecseréltem a &{process{if(<cond>){$_}}} szerkezetekre teljesítmény
okokból.
Íme egy példa a
rekurzióra:
$o1 = [pscustomobject]@{
hashkülönböző = @{
keyegy = @{
key1 = 1
Key2 = 2
}
}
}
$o2 = [pscustomobject]@{
hashkülönböző = @{
keyegy = @{
key1 = 1
Key2 = 3
}
}
}
A fenti két objektum összehasonlítása:
PS C:\> Compare-Property -ReferenceObject $o1 -DifferenceObject $o2
Property Relation r: d:
-------- -------- -- --
hashkülönböző <> {keyegy} {keyegy}
Látható, hogy annak ellenére, hogy minkét objektumnak a hashkülönböző tulajdonságában ugyanolyan kulcsokkal rendelkező hastábla tulajdonságuk van, de mivel a belső keyegy hastábla értékei különbözőek, mégsem tekinthetők egyformának.