【问题标题】:notcontains not working for User objects pulled from AD Groupsnotcontains 不适用于从 AD 组中提取的用户对象
【发布时间】:2019-06-26 06:47:05
【问题描述】:

当使用 notcontains 检查数组中的对象时,当它应该为假时,它会说真。这是我的代码。

$SPSecUsers = Get-ADGroupMember Test
$AllLondon = Get-ADGroupMember Test_AllLondon
$SPSecUKUsers = @()
$SPSecUSUsers = @()

foreach ($SPSecUser in $SPSecUsers) {
    if ($SPSecUser.distinguishedName -match "DC=uk,DC=company,DC=com") {
        $SPSecUKUsers += $SPSecUser
    } else {
        $SPSecUSUsers += $SPSecUser
    }
}

foreach ($UKUser in $AllLondon) {
    if ($SPSecUKUsers -notcontains $UKUser) {
        Write-Host $UKUser.name -ForegroundColor Green
    } else {
        Write-Host $UKUser.name -ForegroundColor Red
    }
}

每次运行时,$SPSecUKUsers -notcontains $UKUser 都会为所有用户显示 True,即使对象在数组中也是如此。

在调试模式下,我手动进行检查,即使用户对象在数组中,它仍然显示 True。

我什至将两个组设置为拥有完全相同的用户,但它仍然不起作用。

【问题讨论】:

  • -contains-in 运算符[及其not 版本] 需要精确匹配。您极不可能看到相同的对象,更不用说完全相同的对象了。尝试使用$Collection.name -notcontains $Item.Name` 或它的一些变体。
  • 我知道它应该是完全匹配的,这很令人困惑,因为用户帐户是同一个帐户。它们是完全相同的 AD 对象。我在调试器中查看了这两个对象,两者之间没有区别。它们在对象中具有所有相同的值。
  • 我在集合和对象上使用了 .name 并且有效。真的很奇怪,比较这两个对象是行不通的。谢谢 Lee_Dailey。
  • 这就是重点。您正在比较两个不同的对象。即使他们代表同一个用户 - 他们是不同的。
  • @JasonPope - 正如olaf 指出的那样,这两个对象看起来相同,但有问题的数组运算符看到 something 不同。我很高兴知道你成功了! [咧嘴]

标签: powershell


【解决方案1】:

tl;dr

不要将 AD 用户对象它们自己存储在您的数组中,而是使用它们的 .SamAccountName 属性值(通常,选择一个唯一标识对象的属性):

# ...
$SPSecUKUsers += $SPSecUser.SamAccountName
# ...
if ($SPSecUKUsers -notcontains $UKUser.SamAccountName) { # ...

如果您想知道为什么存储对象本身不起作用,请参阅下一节。

或者 - 为了更快地查找 - 使用 散列表

$SPSecUKUsers = @{} # initialize hashtabe
# ...
# Create an entry for the object at hand, using its .SamAccountName
# as the entry *key*; you can store the object itself as the entry *value*.
# If all you need are lookups by SAM account name, however, you can just
# use a fixed value such as $true.
$SPSecUKUsers[$SPSecUser.SamAccountName] = $SPSecUser
# ...
if ($SPSecUKUsers.ContainsKey($UKUser.SamAccountName)) { # ...

关于 PowerShell 的包含 (collection-membership) 运算符:

正如 Olaf 和 Lee_Dailey 在 cmets 中暗示的那样,PowerShell 的 containment operators-contains / notcontains-in / -notin 检查 引用相等性(身份)与输入数组的元素,如果这些元素是 .NET reference types 的实例,[string] 实例除外。 [string] 实例和 value types 实例使用
值相等(等价)进行测试 - 请参阅 Equality Comparisons

您可以将这些运算符视为输入数组元素的隐式循环,使用 -eq 运算符(或者,如果您使用区分大小写的变体,例如as -ccontains, with -ceq),使用引用相等或值相等,具体取决于元素类型。

重要提示:由于 PowerShell 灵活的自动类型转换规则,-eq 操作中的 LHS 操作数很重要。 使用-in-contains 意味着隐含的-eq 操作的LHS 是被测试的数组元素,如以下示例所示:

 # `, 10` creates a single-element array
 '0xa' -in , 10       # equivalent of: 10 -eq '0xa' => $true
 , 10 -contains '0xa' # ditto

 # 
 10 -in , '0xa'        # equivalent of: '0xa' -eq 10 => $false
 , '0xa' -contains 10  # ditto

在前 2 个操作中,作为数字 ([int]) 的 LHS 将字符串 RHS ([string]) 也强制为数字 ([int]),并且十六进制“数字字符串”'0xa' 转换为[int] 也有十进制值 10

在后两者中,LHS 为字符串 ([string]) 迫使数字 10 也变为字符串,'10' 显然与 '0xa' 不匹配。

值相等(等价)意味着两个对象具有相同的内容,即使对于不同的值类型对象,该内容根据定义存储在不同的内存位置。

例如,[int][double] 等数值类型是值类型。作为粗略的经验法则,具有属性的对象通常是引用类型。 您可以检查给定类型的.IsValueType 属性;例如,[int].IsValueType 返回$true

引用相等(同一性)意味着两个值仅在它们指向内存中非常相同的对象时才被认为相等,即相同的实例引用类型。

否则,它们被认为是不相等的,即使它们代表概念上相同的实体,这就是你的情况发生的情况:两次单独调用 Get-ADUser 返回 distinct对象,即使您(部分)在两种情况下都请求相同的用户(Get-ADUser 返回类型为 Microsoft.ActiveDirectory.Management.ADUser 的实例,这是一个引用类型)。

例子:

# Create a custom object...
$customObject = [pscustomobject] @{ one = 1; two = 2 }
# which is an instance of a reference type.
$customObject.GetType().IsValueType # -> $false

# Create an array comprising a value-type instance (1)
# and a reference-type instance (the custom object).
$arr = 1, $customObject 

# Look for the value-type instance.
$objectToLookFor = 1

$arr -contains $objectToLookFor # value equality -> $true

# Create another custom object, with the same properties as above.
$objectToLookFor = [pscustomobject] @{ one = 1; two = 2 }

# This lookup *fails*, because $objectToLookFor, despite having the same
# properties as the custom object stored in the array, is a *different object* 
$arr -contains $objectToLookFor # reference equality -> $false(!)

# If we look for the very same object stored in the array, the lookup
# succeeds.
$arr -contains $customObject # -> $true

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多