Fiddle Freak
Fiddle Freak

Reputation: 2051

Include specific SamAccountName Value in filter in directorysearcher .net class

I have the following code that works and exports all the users for the domain...

$SamAccountName = "JohnDoe"
$domainSearchProperties = @('SamAccountName','LastLogon', 'DistinguishedName')
$domainDisplayOutputProperties = @('SamAccountName','LastLogon')
$domainConnector = 'www.myplayground.com'
$domainName = 'MyPlayground'
$outputFile = 'C:\Scripts\Tests\testresults.csv'

Function SearchSingleDomainAndExportContents
{
    Param ([String]$SamAccountName, [String[]]$domainSearchProperties, [String[]]$domainDisplayOutputProperties, [String]$domainConnector, [String]$domainName)

    Write-Host "Starting sub-process to search with SamAccountName $SamAccountName in $domainName"
    $searchDomainResultsTable = powershell -command {
        Param ([String]$SamAccountName, [String[]]$domainSearchProperties, [String[]]$domainDisplayOutputProperties, [String]$domainConnector, [String]$domainName)
        $domain = "LDAP://$domainConnector"

        $adDomain = New-Object System.DirectoryServices.DirectoryEntry($domain)
        $adSearcher = New-Object System.DirectoryServices.DirectorySearcher($adDomain)
        $adSearcher.Filter = '(&(objectCategory=User)(samAccountType:1.2.840.113556.1.4.803:=805306368))'
        $adSearcher.PageSize=1000
        $adSearcher.PropertiesToLoad.AddRange($domainSearchProperties) | out-Null
        $userRecords = $adSearcher.FindAll()
        $adSearcher.Dispose() | Out-Null
        [System.GC]::Collect() | Out-Null

        # The AD results are converted to an array of hashtables.
        $userPropertiesTable = @()
        foreach($record in $userRecords) {
            $hashUserProperty = @{}
            foreach($userProperty in $domainSearchProperties){
                if (($userProperty -eq 'objectGUID') -or ($userProperty -eq 'objectSid') -or ($userProperty -eq 'msExchMasterAccountSid')) {
                    if ($record.Properties[$userProperty]) {
                        $hashUserProperty.$userProperty = $record.Properties[$userProperty][0]
                    } else {
                    $hashUserProperty.$userProperty = $null
                    }
                } Else {
                    if ($record.Properties[$userProperty]) {
                        $hashUserProperty.$userProperty = ($record.Properties[$userProperty] -join '; ').trim('; ')
                    } else {
                    $hashUserProperty.$userProperty = $null
                    }
                } #end Else
            } #end ForEach
            $userPropertiesTable += New-Object PSObject -Property $hashUserProperty
        } #end ForEach
        [System.GC]::Collect() | Out-Null

        # Fixes the property values to be a readable format before exporting to csv file
        $listOfBadDateValues = '9223372036854775807', '9223372036854770000', '0'
        $maxDateValue = '12/31/1600 5:00 PM'
        $valuesToFix = @('lastLogonTimestamp', 'AccountExpires', 'LastLogon', 'pwdLastSet', 'objectGUID', 'objectSid', 'msExchMasterAccountSid')
        $valuesToFixCounter = 0
        $valuesToFixFound = @($false, $false, $false, $false, $false, $false, $false)

        ForEach ($valueToFix in $valuesToFix)
        {
            if ($domainDisplayOutputProperties -contains $valueToFix)
            {
                $valuesToFixFound[$valuesToFixCounter] = $true
            }
            $valuesToFixCounter++
        }

        $tableFixedValues = $userPropertiesTable | % { 
            if ($valuesToFixFound[0]) {
                if ($_.lastLogonTimestamp) {
                    $_.lastLogonTimestamp = ([datetime]::FromFileTime($_.lastLogonTimestamp)).ToString('g')
                }
            }; if ($valuesToFixFound[1]) {
                if (($_.AccountExpires) -and ($listOfBadDateValues -contains $_.AccountExpires)) {
                    $_.AccountExpires = ""
                } else {
                    if (([datetime]::FromFileTime($_.AccountExpires)).ToString('g') -eq $maxDateValue) {
                        $_.AccountExpires = ""
                    } Else {
                        $_.AccountExpires = ([datetime]::FromFileTime($_.AccountExpires)).ToString('g')
                    }
                }
            }; if ($valuesToFixFound[2]) {
                if (($_.LastLogon) -and ($listOfBadDateValues -contains $_.LastLogon)) {
                    $_.LastLogon = ""
                } else {
                    if (([datetime]::FromFileTime($_.LastLogon)).ToString('g') -eq $maxDateValue) {
                        $_.LastLogon = ""
                    } Else {
                        $_.LastLogon = ([datetime]::FromFileTime($_.LastLogon)).ToString('g')
                    }
                }
            }; if ($valuesToFixFound[3]) {
                if (($_.pwdLastSet) -and ($listOfBadDateValues -contains $_.pwdLastSet)) {
                    $_.pwdLastSet = ""
                } else {
                    if (([datetime]::FromFileTime($_.pwdLastSet)).ToString('g') -eq $maxDateValue) {
                        $_.pwdLastSet = ""
                    } Else {
                        $_.pwdLastSet = ([datetime]::FromFileTime($_.pwdLastSet)).ToString('g')
                    }
                }
            }; if ($valuesToFixFound[4]) {
                if ($_.objectGUID) {
                    $_.objectGUID = ([guid]$_.objectGUID).Guid
                } Else {
                    $_.objectGUID = ""
                }
            }; if ($valuesToFixFound[5]) {
                if ($_.objectSid) {
                    $_.objectSid  = (New-Object Security.Principal.SecurityIdentifier($_.objectSid, 0)).Value
                } Else {
                    $_.objectSid = ""
                }
            }; if ($valuesToFixFound[6]) {
                if ($_.msExchMasterAccountSid) {
                    $_.msExchMasterAccountSid  = (New-Object Security.Principal.SecurityIdentifier($_.msExchMasterAccountSid, 0)).Value
                } Else {
                    $_.msExchMasterAccountSid = ""
                }
            };$_}
            [System.GC]::Collect() | Out-Null

            $sortedUserPropertiesTable = $tableFixedValues | Select-Object $domainDisplayOutputProperties
            $finalDomainUserPropertiesTable = $sortedUserPropertiesTable | Select-Object -Property @{Name="Domain Name";Expression={$domainName}}, *
            [System.GC]::Collect() | Out-Null

            return $finalDomainUserPropertiesTable
    } -args $SamAccountName, $domainSearchProperties, $domainDisplayOutputProperties, $domainConnector, $domainName
    [System.GC]::Collect() | Out-Null
    Write-Host "Search Complete."
    Write-Host ""

    Write-Output $searchDomainResultsTable
}

$table = @()
$table += SearchSingleDomainAndExportContents $SamAccountName $domainSearchProperties $domainDisplayOutputProperties $domainConnector $domainName

$table | Export-Csv $outputFile -NoTypeInformation -Force

Since the domain is so large (235k users), and I only care about finding one SamAccountName, I want to filter only by that SamAccountName.

To do this, I have changed the following line from...

        $adSearcher.Filter = '(&(objectCategory=User)(samAccountType:1.2.840.113556.1.4.803:=805306368))'

To

        $adSearcher.Filter = '(&(objectCategory=User)(samAccountType:1.2.840.113556.1.4.803:=805306368)(sAMAccountName=$SamAccountName))'

Now when i run it again, I get the following error...

Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null.
At C:\Scripts\Tests\testme.ps1:383 char:24
+     $searchResultsTable | Export-Csv $outputFile -NoTypeInformation -F ...
+                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Export-Csv], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCsvCo
   mmand

I've tried googling different ways to use the filter, but all suggestions fail. I know that SamAccountName exists, I think I'm just not using the filter right.

Can anyone help me?

Upvotes: 0

Views: 585

Answers (1)

Bob M
Bob M

Reputation: 942

Change from single quotes to double quotes on your search filter. Single quotes do not substitute Powershell variables in strings. A string is interpreted literally, so in this case your filter is searching for a samAccountName that is literally called "$SamAccountName" rather than the value of the variable $SamAccountName.

Upvotes: 1

Related Questions