Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
(AD)PowerShell中的对象相等_Powershell_Active Directory - Fatal编程技术网

(AD)PowerShell中的对象相等

(AD)PowerShell中的对象相等,powershell,active-directory,Powershell,Active Directory,我觉得下面这句话很奇怪: $user1 = Get-ADUser sameuser $user2 = Get-ADUser sameuser $user1 -eq $user2 # -> false # the same for groups: $group1 = Get-ADGroup samegroup $group2 = Get-ADGroup samegroup $group1 -eq $group2 # -> fals

我觉得下面这句话很奇怪:

$user1 = Get-ADUser sameuser
$user2 = Get-ADUser sameuser
$user1 -eq $user2                # -> false
# the same for groups:
$group1 = Get-ADGroup samegroup
$group2 = Get-ADGroup samegroup
$group1 -eq $group2              # -> false
实际上,Powershell用户似乎很高兴
1-eq 1
是真的。此外:

"1" -eq 1           # -> true
@("1") -contains 1  # -> true
但是:

除了这些有趣的行为,真正令人沮丧的是我不能简单地这样做:

$ones      = Get-ADPrincipalGroupMembership one
$seconds   = Get-ADPrincipalGroupMembership second
$excl_ones = $ones | ? { $_ -notin $seconds }
但我们必须这样做:

$second_nms = $seconds | % name
$excl_ones = $ones | ? { $_.name -notin $second_nms }

<>我错过了什么?

理解你看到的一些怪癖。我们必须后退一步,考虑更大的画面,即框架PuthSek是建立在:.NET! NET中的对象相等
$user1-eq$user2
失败,因为
$user1
$user2
是两个不同的对象,尽管它们在Active Directory中可能代表同一个对象

当谈到.NET中的对象相等时,您需要区分值相等和引用相等

值类型的两个变量,例如
[int]
,如果其基础值相同,则视为相等:

$a = 1
$b = 1
$a.Equals($b) # $true
引用类型的两个变量(任何非值类型的变量)通常只有在具有相同标识时才被视为相等,即它们引用内存中的同一对象:

$a = New-Object object
$b = New-Object object
$a.Equals($b) # $false
据我们所知,
$a
$b
完全相同,但它们指的是内存中两个不同的
[object]
实例

类型定义可以覆盖
GetHashCode()
(用于确定对象标识的函数)和
Equals()
(用于确定两个对象之间的相等性的函数),因此您可能会发现一些引用类型在比较它们时似乎充当值类型-
[string]
是一个主要示例:

$a = "test"
$b = "test"
$a.Equals($b)
ADEntity
类(ActiveDirectory模块中所有输出对象的基本类型)不会尝试这样的操作,这就是为什么您会看到这样做的结果

PowerShell中的集合筛选 以上并不能完全解释你提出的另一件奇怪的事情,即:

$a1 = @(1;2;3)
$a2 = @(1;2;3)
$a1 -eq $a2 # NOTHING! WHAT'S GOING ON HERE?
要了解这里发生了什么,您需要研究PowerShell本身中的比较运算符行为

所有比较运算符(
-eq
-ne
-gt
-like
-match
等)都支持两种不同的模式,具体取决于左侧参数:标量和过滤

标量比较 在标量模式下,比较运算符将单个对象作为其左侧操作数,值表达式作为其右侧操作数,并返回布尔结果:
$true
$false

使用比较运算符进行过滤 在筛选模式下,比较运算符将集合(数组或列表)作为其左侧操作数,将值表达式作为其右侧操作数(与前面一样),并返回左侧集合中满足比较的所有单个成员

要查看此操作,请尝试以下操作:

$names  = "James","Jane","John"
$prefix = "Ja"

$names -like "$prefix*"
您将看到
-like
操作返回两个字符串-
James
Jane

如果我们把这些新发现的知识应用到你的例子中

@(1;2;3) - eq @(1;2;3)
很明显,为什么什么都不返回-左手操作数显然是一个数组,随后的比较(
1-eq@(1;2;3)
2-eq@(1;2;3)
等)都不会返回
$true


现在进入问题的实际部分。Active Directory的设计方式使目录中的每个对象都有一个唯一的标识符,您可以使用该标识符来确定它的标识—
objectGUID
值。NET中的
GUID
恰好是一种值类型,因此您可以安全地将其用作比较的基础:

$ones      = Get-ADPrincipalGroupMembership one
$seconds   = Get-ADPrincipalGroupMembership second
$excl_ones = $ones | ? { $_.objectGUID -notin $seconds.objectGUID }

对于安全主体(组、用户、计算机等),另一个可以安全使用的唯一标识符是
objectSID
-安全标识符始终是唯一的。

您应该始终在其
objectGUID
值上比较AD对象您的
$a1-eq$a2
没有返回值,因为将运算符与左侧的数组一起使用可以作为对数组内容的过滤器。它不是询问数组1是否等于数组2,而是询问$a1中所有等于$a2的项。比较
@(1,2,1,2)-eq 2
@tessellingheckler这实际上是我不知道的一个很好的特性。但人们当然可以说,一致性看起来不同
@(1,2,1,2)-eq 2->@(2,2)
2-eq(1,2,1,2)->false
@TNT我认为这种设计对于“小于10的所有值”更有意义:
@(1,4,12,16)-lt 10
而不是“2的所有值”,对于文本来说更是如此,所有匹配正则表达式的行:
@(“line1”,“line2”,“line3”)-匹配'e[13]“
那么你就不指望反向模式“十大于一个数字数组”或
'e[13]-匹配@(“第1行”、“第2行”、“第3行”)
会有同样的意义。哇!谢谢,这真是太棒了(我指的是实用部分)!我还没有完全理解它,但乍一看,这个(我指的是数组属性,它包含数组内容的各个属性的数组)似乎比RubyonRails的ActiveRecord类的model_id方法更优雅。这会让我今晚睡得更好。
('h'、'u'、'r'、'r'、'a'{{yes=$})。是的
很棒的解释@Mathias。我编辑了标题并用相等替换了身份,因为正如你说得对的,这就是我实际上在说的。@TNT我更新了答案,有点关于
@(1;2;3)-eq(1;2;3)
之谜
$ones      = Get-ADPrincipalGroupMembership one
$seconds   = Get-ADPrincipalGroupMembership second
$excl_ones = $ones | ? { $_.objectGUID -notin $seconds.objectGUID }