0

I have ran the following code to query AD for either the first or second name. If I enter "conor" as the input I get the expected results which contains two users, but if I enter "timms" (surname of same user) I get the following error: Method invocation failed because [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection] does not contain a method named 'op_Subtraction'.

$exists = $true
            while ($exists -eq $true) {
                $search = Read-Host -Prompt "Enter first name or surname name of user"
                $results = Get-ADUser -Filter "Name -like '*$search*'"
                if ($results) {
                    Write-Output "You're in one"
                    for ($i = 0; $i -le $results.count - 1; $i++) {
                        $i
                        $results[$i] | Select-Object Name, SamAccountName | Format-Table
                    }
                }else {
                    Write-Host "Name does not match any of the users in domain"
                    $exists = $false
                }
            }

Output with conor as input:

Enter first name or surname name of user: conor
You're in one
0

Name        SamAccountName
----        --------------
Conor Timms Conor.Timms

1

Name        SamAccountName
----        --------------
Conor Admin ConorAdmin

Output with timms as input:

Enter first name or surname name of user: timms
You're in one
InvalidOperation:
Line |
   7 |                      for ($i = 0; $i -le $results.count - 1; $i++) {
     |                                   ~~~~~~~~~~~~~~~~~~~~~~~~~
     | Method invocation failed because [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection] does not contain a method named 'op_Subtraction'.
Enter first name or surname name of user:
  • What happens if you change `$i -le $results.count - 1` to `$i -lt @($results).Count`? – Mathias R. Jessen May 04 '21 at 14:26
  • Try `$results = @(Get-ADUser -Filter "Name -like '*$search*'")` – JosefZ May 04 '21 at 14:32
  • @JosefZ This has done the trick, thanks! Would you be so kind as to explain what this does exactly? – Conor Timms May 04 '21 at 14:44
  • Does this answer your question? [PowerShell: How can I to force to get a result as an Array instead of Object](https://stackoverflow.com/questions/14085077/powershell-how-can-i-to-force-to-get-a-result-as-an-array-instead-of-object) and [more results about the same topic](https://stackoverflow.com/search?q=%5Bpowershell%5D+get+always+array) – JosefZ May 04 '21 at 14:54

2 Answers2

0

Based on the error format it looks like you are doing this in PowerShell 7+. If so, it may be loading an implicit session and therefore may serialize the objects such that the methods are stripped off. This is important to keep in mind regardless.

That said, even with regular arrays you don't have to do -le $array.Count -1. The loop will run as long as the condition is true, so in a [0] based array the condition $i -lt $Array.Count will remain perfectly true right up to the point that you'd go out of bounds. Therefore it's more simple in general and may well solve this problem.

Note: @MathiasRJessen, implied the same in his comment.

$exists = $false
while ( !$exists ) {
    $search = Read-Host -Prompt "Enter first name or surname name of user"
    $results = @(Get-ADUser -Filter "Name -like '*$search*'")
    if ($results) {
        Write-Output "You're in one"
        for ($i = 0; $i -lt $results.count; $i++) {
            $i
            $results[$i] | Select-Object Name, SamAccountName | Format-Table
        }
    }else {
        Write-Host "Name does not match any of the users in domain"
        $exists = $true
    }
}

Note: I also changed $exists initial value to false. I just think that's a more typical practice.

Above is combined with @JoseZ's comment to wrap the Get-ADUser command in an array subexpression so you guarantee an array result. Otherwise in cases where you have only 1 result a scalar will be returned.

Note: The looping challenge may have been more easily handled using one of the ForEach constructs.

$exists = $false
while ( !$exists ) {
    $search = Read-Host -Prompt "Enter first name or surname name of user"
    $results = Get-ADUser -Filter "Name -like '*$search*'"
    if ($results) {
        Write-Output "You're in one"
        ForEach( $Result in $results )
        {
            $result | Select-Object Name, SamAccountName | Format-Table
        }        
    }else {
        Write-Host "Name does not match any of the users in domain"
        $exists = $true
    }
}

In this case you do not need to use a traditional For loop and it wouldn't matter is a whether a scalar or an array is returned.

Steven
  • 6,817
  • 1
  • 14
  • 14
0

Changing $results = Get-ADUser -Filter "Name -like '*$search*'" to $results = @(Get-ADUser -Filter "Name -like '*$search*'") fixed the issue.

The reason is that if the query returns one object then it is stored as an object. If the results returns 2 or more then they are stored as an array.

Thank @JosefZ