arrayspowershellmember-access-enumeration

Powershell Array Issue when one item found


I have created a script to automate some AD User account modification tasks. The user is prompted to enter a partial last name which is used to look up any user account that matches the search criteria. I found my code has a mistake in my logic. It works fine if it finds multiple matches - it will list each with the appropriate info, and it works ine if there are 0 matches - it returns a "User Not Found" message. An issue only occurs if there is only 1 match found - in this case it returns an array of every letter of the users name and UserID. I suspect it how I constructed my array but don't know for sure. Any suggestions?

One Match (Issue):strong text enter image description here

Multiple Matches (Works Fine): enter image description here

No Matches (Works Fine): enter image description here

Where I suspect issue is: enter image description here

Code:

#prompt for last name (or at least portion of last name, then conver to a string with wild card for use in filter
$ticketNum = Read-Host "`nEnter the ServiceNow Ticket Number"
$lname = Read-Host "`nEnter at least the first three chars of users last name (you may enter full last name)"
$search = $lname + "*"

#Empty arrays
$ResultsArray=@("")
$ADUsersList=@("")

#add aduser properties to array, return error and exit if no user found
$ADUsersList += Get-ADUser -filter 'surname -like $search' -Properties * | select name,samaccountname,DistinguishedName,Enabled
if ($ADUsersList.count -le 1){
    Write-host "USER NOT FOUND"
    return
}

#populate a 2D array with NAM and with UserID
$ResultsArray = @(($ADUsersList.name),($ADUsersList.samaccountname),($ADUsersList.enabled))

Write-host "`t NAME `t`t`t USER ID `t`t ACCOUNT ENABLED"
#return list of found users and user ids. Preface with index number to use for selection menu
for($i=0;$i-le $ResultsArray[0].length-1;$i++){
    “[{0}] = {1} `t `t {2} `t `t {3}” -f $i,$ResultsArray[0][$i],$ResultsArray[1] [$i],$ResultsArray[2][$i] 
}

#Prompt 
$selection = (Read-Host "`nEnter number for user you want to modify") -as [uint32]

#Input validation - Only allow a valid index #.  If valid, write user selected to screen before proceeding 
if ($selection -notmatch '^[0-9]+$' -or $selection -gt $ResultsArray[0].length -or $selection -lt 0){
    Write-host "INVALID SELECTION!!!" -ForegroundColor Red
} 
else {
    Write-Host "`nYou selected user " -nonewline 
    Write-Host $ResultsArray[0][$selection] -nonewline -ForegroundColor Green
    Write-Host " with user ID a of " -nonewline 
    Write-Host $ResultsArray[1][$selection] -nonewline -ForegroundColor Green
    $proceed = Read-Host "`nProceed with disabling for Leave Of Absence? (y or n)"
    if($proceed -eq "y"){
        Write-Host "proceeding ..."
        $target = $ResultsArray[1][$selection]
        $aduser = Get-ADUser -Identity $target -Properties *
        $prepend = "DISABLED per HR for LOA ($ticketNum) - "
        $desc = $aduser.description
        $loaDesc = $prepend + $desc
        Set-ADUser -Identity $target -description $loaDesc
        Disable-ADAccount -Identity $target
    }
    else{
        Write-host "no changes will be made"
        break
    }
}

Solution

  • The problem is this statement right here:

    #populate a 2D array with NAM and with UserID
    $ResultsArray = @(($ADUsersList.name),($ADUsersList.samaccountname),($ADUsersList.enabled))
    

    If $ADUsersList contains 1 object then $ResultsArray will no longer be a nested array - it'll be a flat array consisting of the three property values from that 1 user.

    You can force the inner expressions to evaluate to arrays with the array subexpression operator @(...):

    $ResultsArray = @(@($ADUsersList.name), @($ADUsersList.samaccountname), @($ADUsersList.enabled))
    

    ... but a better way would be to forego the $ResultsArray step completely - you already have an array of objects with the relevant properties attached stored in $ADUsersList:

    # ...
    
    #add aduser properties to array, return error and exit if no user found
    $ADUsersList = @(Get-ADUser -filter 'surname -like $search' -Properties * | select name,samaccountname,DistinguishedName,Enabled)
    
    if ($ADUsersList.count -le 1){
        Write-host "USER NOT FOUND"
        return
    }
    
    # skip the `$ResultsArray` step completely
    
    Write-host "`t NAME `t`t`t USER ID `t`t ACCOUNT ENABLED"
    #return list of found users and user ids. Preface with index number to use for selection menu
    for ($i = 0; $i -le $ADUsersList.Count; $i++) {
        "[{0}] = {1} `t `t {2} `t `t {3}" -f $i,$ADUserlist[$i].Name,$ADUserlist[$i].SAMAccountName,$ADUserlist[$i].Enabled
    }