Boolean 'if' statement in a loop.

This is a very cut down version of my actual script, but it essentially highlights my problem.
I want to do a series of checks against some users, but after an initial run though, some of the criteria for a user may change, so I want to loop through the users again any number of times set in a parameter (for this example it is only 2).

My issue is that the -contains parameter doesn’t work and is always $false in the if statement.
All my users are getting added in twice, I can’t use -match or -like as they are not accurate enough, as it needs to be an exact match.

If I add ($Batch -contains $objUser) after ($Batch += $objUser), it shows $true, but on the next loop, the if statement is still $false when it comes up to a user with the same name in the batch.

How do I get this to work?

Input CSV:
UserName
User1
User2
User3
User4
User5
User5

$Batch = @()
$Loop=2
$Users=Get-Content -Path $InputFile

for($counter = 1; $counter -le $Loop; $counter++)
{
    Write-Output `n "RUNNING LOOP #$counter" `n

    foreach ($User in $Users)
    {
        $objUser = New-Object System.Object
        $objUser |  Add-Member -type NoteProperty -name UserName -value $User.UserName
      
        if 
        ($Batch -contains $objUser)
        {
            Write-Output "$($objuser.UserName) already exists in current batch; Ignore user."
        }
        else
        {
            Write-Output "$($objuser.UserName) does not exist in current batch; Adding user."
            $Batch += $objUser                  
        }
    }
}

If you use a csv you should use ‘import-CSV’.

$Batch = @()
$Loop=2
$Users=Import-Csv -Delimiter ',' -Path $InputFile

for($counter = 1; $counter -le $Loop; $counter++)
{
    Write-Output `n "RUNNING LOOP #$counter" `n

    foreach ($User in $Users)
    {
        $objUser = New-Object System.Object
        $objUser |  Add-Member -type NoteProperty -name UserName -value $User.UserName
        
        if 
        ($Batch.UserName -contains $objUser.UserName)
        {
            Write-Output "$($objuser.UserName) already exists in current batch; Ignore user."
        }
        else
        {
            Write-Output "'$($objuser.UserName)' does not exist in current batch; Adding user ."
            $Batch += $objUser    
        }
    }
}

$Batch -contains does not work because $Batch contain object and not string. PS tries to find object reference, but not object with same properties.

Olaf’s solution not good because of using $Batch.UserName - on each loop powershell will extract UserName value from all $Batch objects, collect it to another internal array and conpare it with $objUser.UserName. it’s sooo sloooooow…

the simpliest way to solve your problem: use hashtables

#Init empty collection
$Batch = @{}
.......
#Fill collection (inside cycle)
if ($Batch.ContainsKey($User.UserName)) {
  "Ignore user $($User.UserName)"
}
else {
  $Batch[$User.UserName] = $User
}
.........
#Use the collection
$Batch.GetEnumerator() | Foreach-Object {
  $User = $_.Value
  $User.UserName
}

Hi Olaf,

Sorry, this was due to me trying to simply things for this post, the input file I have to work from is not formatted correctly so I have to use:

$Users=Get-Content -Path $InputFile | Select-Object -Skip 1 | Out-String | ConvertFrom-Csv | Where-Object {($_.'UserName' -ne '')}

But thanks, yes, for this example I’ll change it to:

$Users=Import-Csv -Delimiter ',' -Path $InputFile

Did you try my code? Did it work then? I did change more than just the csv thing! Did you try Max’s approach?

$users is already an array of objects. Why would you try to build another?

Maybe I was being lazy, the full script has multiple headings in the CSV, the values, some are integers, some boolean, some string.
I created the new object to ensure that all the headings were stored in the correct format, rather than all as string from an Import-CSV / Get-Content.

You don’t answer questions. Did you solve your problem? If not - what exactly is your problem?