Private/Get-DirectoryEntryByUsername.ps1

function Get-DirectoryEntryByUsername {
    <#
        .SYNOPSIS
        Retrieves a DirectoryEntry object for a specified username.
 
        .DESCRIPTION
        This function searches Active Directory for a user account based on the provided username
        and returns the corresponding DirectoryEntry object. The function can handle various
        username formats including sAMAccountName, userPrincipalName, and distinguished name.
 
        .PARAMETER Username
        The username to search for. Can be in various formats:
        - sAMAccountName (e.g., "testuser")
        - Domain\Username (e.g., "DOMAIN\testuser")
        - userPrincipalName (e.g., "testuser@domain.com")
        - Distinguished Name (e.g., "CN=Test User,OU=Users,DC=domain,DC=com")
 
        .INPUTS
        System.String
        Username string in various supported formats.
 
        .OUTPUTS
        System.DirectoryServices.DirectoryEntry
        Returns a DirectoryEntry object representing the user account, or $null if not found.
 
        .EXAMPLE
        # Get DirectoryEntry by sAMAccountName
        $user = Get-DirectoryEntryByUsername -Username "testuser"
 
        .EXAMPLE
        # Get DirectoryEntry by domain\username format
        $user = Get-DirectoryEntryByUsername -Username "DOMAIN\testuser"
 
        .EXAMPLE
        # Get DirectoryEntry by UPN
        $user = Get-DirectoryEntryByUsername -Username "testuser@domain.com"
 
        .EXAMPLE
        # Pipeline usage
        "testuser" | Get-DirectoryEntryByUsername
 
        .NOTES
        This function requires Active Directory access and appropriate permissions to query
        user objects. The function will attempt to resolve the username using multiple
        search methods to handle different input formats.
         
        The returned DirectoryEntry object can be used with other ESCalator functions
        that require DirectoryEntry parameters, such as Find-ESC4e1.
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        [string]$Username
    )


    begin {
        Write-Verbose "[$(Get-Date -Format 'yyyy-MM-dd hh:mm:ss')] Starting $($MyInvocation.MyCommand) on $env:COMPUTERNAME..."
    }

    process {
        try {
            Write-Verbose "Searching for user: $Username"
            
            # Initialize variables
            $directoryEntry = $null
            $searchFilter = $null
            
            # Clean up the username and determine search strategy
            $cleanUsername = $Username.Trim()
            
            # Check if it's a Distinguished Name (starts with CN=)
            if ($cleanUsername -match '^CN=.*,.*DC=') {
                Write-Verbose "Username appears to be a Distinguished Name"
                try {
                    $directoryEntry = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$cleanUsername")
                    # Verify the object exists by accessing a property
                    $null = $directoryEntry.Properties['objectClass'].Value
                    Write-Verbose "Found user by DN: $($directoryEntry.Properties['distinguishedName'].Value)"
                    return $directoryEntry
                } catch {
                    Write-Verbose "Failed to find user by DN: $($_.Exception.Message)"
                    return $null
                }
            }
            
            # Check if it's a UPN (contains @)
            if ($cleanUsername -contains '@') {
                Write-Verbose "Username appears to be a UPN"
                $searchFilter = "(&(objectClass=user)(userPrincipalName=$cleanUsername))"
            }
            # Check if it's domain\username format
            elseif ($cleanUsername -contains '\') {
                Write-Verbose "Username appears to be in DOMAIN\Username format"
                $parts = $cleanUsername -split '\\'
                if ($parts.Length -eq 2) {
                    $samAccountName = $parts[1]
                    $searchFilter = "(&(objectClass=user)(sAMAccountName=$samAccountName))"
                } else {
                    Write-Warning "Invalid DOMAIN\Username format: $cleanUsername"
                    return $null
                }
            }
            # Assume it's a sAMAccountName
            else {
                Write-Verbose "Treating username as sAMAccountName"
                $searchFilter = "(&(objectClass=user)(sAMAccountName=$cleanUsername))"
            }
            
            # Perform LDAP search
            Write-Verbose "Using search filter: $searchFilter"
            
            # Get domain root
            $rootDSE = New-Object System.DirectoryServices.DirectoryEntry("LDAP://RootDSE")
            $defaultNC = $rootDSE.Properties["defaultNamingContext"].Value
            $domainRoot = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$defaultNC")
            
            # Create DirectorySearcher
            $searcher = New-Object System.DirectoryServices.DirectorySearcher($domainRoot)
            $searcher.Filter = $searchFilter
            $searcher.SearchScope = [System.DirectoryServices.SearchScope]::Subtree
            
            # Perform search
            $searchResult = $searcher.FindOne()
            
            if ($searchResult) {
                $directoryEntry = $searchResult.GetDirectoryEntry()
                $foundUsername = $directoryEntry.Properties['sAMAccountName'].Value
                $foundDN = $directoryEntry.Properties['distinguishedName'].Value
                Write-Verbose "Found user: $foundUsername ($foundDN)"
                return $directoryEntry
            } else {
                Write-Warning "User not found: $Username"
                return $null
            }
            
        } catch {
            Write-Error "Failed to retrieve DirectoryEntry for user '$Username': $($_.Exception.Message)"
            Write-Verbose "Exception details: $($_.Exception.ToString())"
            return $null
        } finally {
            # Clean up searcher if it was created
            if ($searcher) {
                $searcher.Dispose()
            }
        }
    }

    end {
        Write-Verbose "[$(Get-Date -Format 'yyyy-MM-dd hh:mm:ss')] Finishing $($MyInvocation.MyCommand) on $env:COMPUTERNAME..."
    }
}