tl; dr
Не сохраняйте пользовательские объекты AD себя в своих массивах, вместо этого используйте их значение свойства .SamAccountName
(обычно выбирайтесвойство, которое однозначно идентифицирует объекты):
# ...
$SPSecUKUsers += $SPSecUser.SamAccountName
# ...
if ($SPSecUKUsers -notcontains $UKUser.SamAccountName) { # ...
См. следующий раздел, если вы хотите узнать, почему хранение самих объектов не работает.
В качестве альтернативы - для более быстрого поиска - используйте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 (членство в коллекции):
Как подразумевают Олаф и Lee_Daily в комментариях, PowerShell операторы сдерживания (-contains
/ notcontains
и -in
/ -notin
) проверить операнд сравнения для равенство ссылок (тождество) с элементами входного массива, если эти элементы являются экземплярами .NET ссылочных типов , за исключением [string]
экземпляров, которые обрабатываются как значения типов , которые тестируются с
значение равенства (эквивалентность) - см. Сравнения равенства .
Вы можете рассматривать операторы множеств как неявный цикл над элементами входного массива, проверяя каждый из них с операндом сравнения с помощью -eq
оператор (или, если вы используете регистрозависимый вариант, такой как -ccontains
, с -ceq
), с использованием равенства ссылок или значений в зависимости от типа элемента.
Важно : Из-за гибких правил автоматического преобразования типов PowerShell, операндом является LHS в операции -eq
. Использование -in
или -contains
означает, что LHS подразумеваемой операции -eq
является элементом массива , проверяемым по , как показывают следующие примеры:
# `, 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
В первых двух операциях LHS, являющийся числом ([int]
), также переводит строку RHS ([string]
) в число ([int]
), а шестнадцатеричная «строка чисел» '0xa'
преобразуетв [int]
с десятичным значением 10
.
В последних 2 LHS, являющийся строкой ([string]
), заставляет число 10
также стать строкой, а '10'
очевидно, не совпадает '0xa'
.
Значение равенства (эквивалентность) означает, что два объекта имеют одинаковое содержимое , хотя,с различными объектами типа значения этот контент по определению хранится в разных местах памяти.
Числовые типы, такие как [int]
и [double]
, например, являются типами значений.Как правило грубое , объекты, которые имеют свойства , часто являются ссылочными типами.Вы можете проверить свойство .IsValueType
данного типа;Например, [int].IsValueType
возвращает $true
.
Ссылочное равенство (тождество) означает, что два значения считаются равными, только если они указывают на очень один и тот же объект впамять , т. е. тот же экземпляр ссылочного типа.
В противном случае они считаются не равными, даже если они представляют концептуально одного и того же объекта,что и произошло в вашем случае: два отдельных вызова Get-ADUser
возврат различных объектов , даже если вы (частично) запрашиваете одних и тех же пользователей в обоих случаях (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