Powershell - match with Containskey & set value of hashtable don't work

16,485

Solution 1

I have solved this by assign the samAccountName value to another variable:

$tmpAccountName = $inuser.samAccountName

then

If ($arrUsers.ContainsKey("$tmpAccountName"))

instead of throw the $inuser.samAccountName directly to the checking. Not so sure why it cannot be read directly however at least it is solved now =). Same goes to the problem #2.

Solution 2

You're not using variable expansion correctly. Object properties aren't expanded, so this

"$inuser.samaccountname"

is actually:

$inuser.ToString() + ".samaccountname"

To expand an expression in a string, you must surround it with $(), e.g.

"$($inuser.samaccountname)"

In your case, however, you don't even need to do that. Leave the quotes out entirely:

$arrusers[$DN]
$arrusers.ContainsKey($inuser.samaccountname)

See the about_Quoting_Rules help topic for details.

Share:
16,485
nlks
Author by

nlks

Updated on June 04, 2022

Comments

  • nlks
    nlks about 2 years

    I am working on a script by Richard L. Mueller to disable inactive account in our AD.

    Trap {"Error: $_"; Break;}
    
    $D = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
    $Domain = [ADSI]"LDAP://$D"
    $Searcher = New-Object System.DirectoryServices.DirectorySearcher
    $Searcher.PageSize = 200
    $Searcher.SearchScope = "subtree"
    
    $Searcher.Filter = "(&(objectCategory=person)(objectClass=user))"
    $Searcher.PropertiesToLoad.Add("samAccountName") > $Null
    $Searcher.PropertiesToLoad.Add("lastLogon") > $Null
    $Searcher.PropertiesToLoad.Add("accountExpires") > $Null
    
    # Create hash table of users and their last logon dates.
    $arrUsers = @{}
    
    # Enumerate all Domain Controllers.
    ForEach ($DC In $D.DomainControllers)
        {
    $Server = $DC.Name
    $Searcher.SearchRoot = "LDAP://$Server/" + $Domain.distinguishedName
    
    $Results = $Searcher.FindAll()
    #$Results[100].Properties.item("samAccountName")
    #$Results[100].Properties.item("lastlogon")
    ForEach ($Result In $Results)
        {
            $DN = $Result.Properties.Item("samAccountName")
            $LL = $Result.Properties.Item("lastLogon")
            If ($LL.Count -eq 0)
            {
                $Last = [DateTime]0
            }
            Else
            {
                $Last = [DateTime]$LL.Item(0)
            }
            If ($Last -eq 0)
            {
                $LastLogon = $Last.AddYears(1600)
            }
            Else
            {
                $LastLogon = $Last.AddYears(1600).ToLocalTime()
            }
            If ($arrUsers.ContainsKey("$DN"))
            {
                If ($LastLogon -gt $arrUsers["$DN"])
                {
                    $arrUsers["$DN"] = $LastLogon
                }
            }
            Else
            {
                $arrUsers.Add("$DN", $LastLogon)
            }
        }
    }
    

    Now I have the most updated LastLogon date of my AD users.

    Then I do:

    Foreach ($ou in $searchRoot) {
    $inactiveUsers += @(Get-QADUser -SearchRoot $ou -Enabled -PasswordNeverExpires:$false -CreatedBefore $creationCutoff -SizeLimit $sizeLimit | Select-Object Name,SamAccountName,LastLogonTimeStamp,Description,passwordneverexpires,canonicalName | Sort-Object Name)
    }
    

    I do not use this to disable the ID because LastLogonTimeStamp has a delay being updated from 9-14 days. And with the real last logon date in $arrUsers, I would like to replace LastLogonTimeStamp with it. So I want to match them using the user ID:

    Foreach ($inuser in $inactiveUsers) {
        If ($arrUsers.ContainsKey("$inuser.samAccountName"))
            {
            write-host "True"
            $inuser.LastLogonTimeStamp = $arrUsers["$inuser.samAccountName"]
            $inuser.LastLogonTimeStamp = $inuser.LastLogonTimeStamp.adddays(30)
            If ((Get-Date) -gt $inuser.LastLogonTimeStamp)
                {
                write-host $inuser.samAccountName "should be disabled"
                }
            Else
                {
                write-host $inuser.samAccountName "is still active"
                }
    
            }
        }
        Else
        {
        write-host "False"
        }
    

    I have 2 problems here.

    1. First the "If ($arrUsers.ContainsKey("$inuser.samAccountName"))" doesn't seems working. I always get a false result.
    2. Second, to replace the LastLogonTimeStamp using "$inuser.LastLogonTimeStamp = $arrUsers["$inuser.samAccountName"]", my LastLogonTimeStamp become blank.

    Could someone able to provide some assistants?