I'm currently pulling user data from Ad by OU, then updating certain fields, which works fine. I want to modify the script to only update certain users but struggling, to remove any of the entries from the array as it is a fixed size. I converted to ArrayList and can get count of object, and can query then individually etc..
$users = Get-ADUser -Filter * -SearchBase "DN" -Properties GivenName, Surname,mail,UserPrincipalName,SAMAccountName,proxyAddresses | Select GivenName, Surname,mail,UserPrincipalName,SAMAccountName,proxyAddresses
$WorkingSet =[System.Collections.ArrayList]($users)
$WorkingSet.count
gives 47 as result with last element being:
GivenName: Laura
Surname:Willox
mail:WilloxL@domain
UserPrincipalName :Laura.Willox@domain
SAMAccountName : Laura.Willox
proxyAddresses : {smtp:laura.willox@domain, SMTP:WilloxL@domain}
but trying $WorkingSet.IndexOf('Laura.Willox')
gives -1 instead of 46
So then I can't do something like $WorkingSet.RemoveAt($WorkingSet.IndexOf('Laura.Willox'))
Is something about this data that I am not understanding,that it can't be queried like this?
CodePudding user response:
You absolutely do not need to wrap your data in an ArrayList
, it'll only complicate your code unnecessarily.
Instead of trying to modify the output from Get-ADUser
inline in a list, use PowerShell's Where-Object
cmdlet to filter the data:
$users = Get-ADUser -Filter * -SearchBase "DN" -Properties GivenName, Surname,mail,UserPrincipalName,SAMAccountName,proxyAddresses | Select GivenName, Surname,mail,UserPrincipalName,SAMAccountName,proxyAddresses
# use `Where-Object` to filter the data based on individual property values
$usersSansLaura = $users |Where-Object SAMAccountName -ne 'Laura.Willox'
Here, we pipe any user objects contained in $users
to Where-Object SAMAccountName -ne 'Laura.Willox'
- the -ne
operator is the "not equal" operator, so the output will be any input object that does not have a SAMAccountName
property with the exact value Laura.Willox
, and then assign those to $usersSansLaura
CodePudding user response:
Mathias' helpful answer is worth considering:
- In PowerShell, it is unusual to directly manipulate resizable collections.
- Instead, collection processing in PowerShell usually involves creating new collections by filtering the original collection, using the
Where-Object
in the pipeline or, for collections already in memory, the.Where()
array method.
If you do need to deal with in-place resizing of a list data type, I suggest using System.Collections.Generic.List`1
instead, whose .FindIndex()
method allows you to do what you wanted:
# Note: I'm using [object] as the type parameter for simplicity, but you
# could use [Microsoft.ActiveDirectory.Management.ADUser] for strict typing.
$WorkingSet = [System.Collections.Generic.List[object]]::new(
@(Get-ADUser -Filter * -SearchBase "DN" -Properties GivenName, Surname,mail,UserPrincipalName,SAMAccountName,proxyAddresses | Select GivenName, Surname,mail,UserPrincipalName,SAMAccountName,proxyAddresses)
)
# Find the index of the user with a given SAMAccountName:
$ndx = $WorkingSet.FindIndex({ $args[0].SAMAccountName -eq 'Laura.Willox' })
# If found, remove the user from the list
# (-1 indicates that no matching element was found)
if ($ndx -ne -1) {
$WorkingSet.RemoveAt($ndx)
}
Generally, note that both System.Collections.ArrayList
and System.Collections.Generic.List`1
have a .Remove()
method that allows you to pass the object (element) to remove directly, irrespective of its index.
As for what you tried:
Since your array list is composed of ADUser
instances, the .IndexOf()
method requires passing such an instance in order to locate it among the elements - you can't just pass a string referring to one of the properties among the elements.
Instead, you need a predicate (a Boolean test) that compares the string to the property of interest (.SamAccountName
), which is what the .FindIndex()
call above does.