notcontains 不适用于从 AD 组中提取的用户对象 [英] notcontains not working for User objects pulled from AD Groups

查看:32
本文介绍了notcontains 不适用于从 AD 组中提取的用户对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

When using notcontains to check for an object in array it is saying True when it should be false. This is the code that I have.

$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,即使对象在数组中也是如此.

Every time I run this, $SPSecUKUsers -notcontains $UKUser brings up True for all users, even when object is in the array.

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

In debug mode I manually do a check and it still brings up True even though the User object is in the Array.

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

I have even set both groups to have the exact same users, and it still does not work.

推荐答案

tl;dr

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

Don't store the AD user objects themselves in your arrays, use their .SamAccountName property value instead (generally, pick a property that uniquely identifies the objects):

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

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

See the next section, if you want to know why storing the objects themselves doesn't work.

或者 - 为了更快地查找 - 使用 哈希表:

Alternatively - for faster lookups - use a hashtable:

$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 的遏制(集合-会员)操作符:

正如 Olaf 和 Lee_Daily 在评论中暗示的那样,PowerShell 的 包含操作符(-contains/notcontains-in/-notin) 检查引用相等(身份)与输入数组元素的比较操作数,如果这些元素是的实例>.NET 引用类型,除了 [string] 实例,它们被视为 值类型,使用
进行测试价值相等(等价) - 参见 相等比较.


About PowerShell's containment (collection-membership) operators:

As Olaf and Lee_Daily imply in the comments, PowerShell's containment operators (-contains / notcontains and -in / -notin) check the comparison operand for reference equality (identity) with the elements of the input array, if those elements are instance of .NET reference types, with the exception of [string] instances, which are treated like value types, which are tested with
value equality (equivalence) - see Equality Comparisons.

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

You can think of the set operators as an implicit loop over the input array's elements, testing each against the comparison operand with the -eq operator (or, if you use the case-sensitive variant such as -ccontains, with -ceq), using reference equality or value equality, depending on the element type.

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

Important: Due to PowerShell's flexible automatic type-conversion rules, which operand is the LHS in an -eq operation matters. Using -in or -contains means that the LHS of the implied -eq operation is the array element being tested against, as the following examples show:

 # `, 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 个操作中,LHS 是一个数字 ([int]) 强制字符串 RHS ([string]) 变成一个数字 ([int]) 也是,十六进制数字字符串"'0xa' 转换为带有十进制值 10[int]

In the first 2 operations, the LHS being a number ([int]) forces the string RHS ([string]) to a number ([int]) too, and the hex "number string" '0xa' converts to an [int] with decimal value 10 too.

在后 2 个中,LHS 是一个字符串 ([string]) 迫使数字 10 也变成一个字符串,而 '10' 显然与 '0xa' 不匹配.

In the latter 2, the LHS being a string ([string]) forces the number 10 to become a string too, and '10' obviously doesn't match '0xa'.

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

Value equality (equivalence) means that two objects have the same content, even though, with distinct value-type objects, that content is by definition stored in different memory locations.

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

Numeric types such as [int] and [double] are value types, for instance. As a rough rule of thumb, objects that have properties are often reference types. You can check a given type's .IsValueType property; e.g., [int].IsValueType returns $true.

引用相等(身份)意味着只有当两个值指向内存中非常相同的对象,即相同的实例引用类型.

Reference equality (identity) means that two values are only considered equal if they point to the very same object in memory, i.e., the same instance of a reference type.

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

Otherwise, they're considered not equal, even if they represent what is conceptually the same entity, which is what happened in your case: two separate calls to Get-ADUser return distinct objects, even if you (in part) ask for the same users in both cases (Get-ADUser returns instance of type Microsoft.ActiveDirectory.Management.ADUser, which is a reference type).

示例:

# 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

这篇关于notcontains 不适用于从 AD 组中提取的用户对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆