System.DirectoryServices.DirectorySearcher 没有吸引所有用户

System.DirectoryServices.DirectorySearcher not picking up all the users

我正在尝试备份多个域的用户属性。我需要将所有用户导出到每个域的 csv 文件。已发现 Get-QADUser 在一个速度较慢的域上需要 72 小时。相反,我使用 ``.

出于某种原因,在几个域上它没有吸引所有用户,我不确定为什么。这是我的代码...

function CreateQueriedCsvDataSheet
{
    $csvFileWithPath = 'C:\Scripts\Tests\testResults.csv'
    $DomainControlConnector = 'www.example.com'
    $DomainName = 'myDomain1'
    $domainUserProperties = @('sAMAccountName', 'msRTCSIP-UserEnabled', 'msRTCSIP-OptionFlags', 'msRTCSIP-PrimaryUserAddress', 'msRTCSIP-PrimaryHomeServer', 
    'mail', 'msExchMasterAccountSid', 'homeMDB', 'proxyaddresses', 'legacyExchangeDN', 
    'lastLogonTimestamp', 'logonCount', 'lastLogoff', 'lastLogon', 'pwdLastSet', 'userAccountControl', 'whenCreated', 'whenChanged', 'accountExpires', 
    'sn', 'givenName', 'displayName', 'distinguishedName', 'initials', 'l', 'st', 'street', 'title', 'description', 'postalCode', 'physicalDeliveryOfficeName', 'telephoneNumber', 'facsimileTelephoneNumber', 'info', 'memberOf', 'co', 'department', 'company', 'streetAddress', 'employeeNumber', 'employeeType', 'objectGUID', 'employeeID', 'homeDirectory', 'homeDrive', 'scriptPath', 'objectSid', 'userPrincipalName', 'url', 'msDS-SourceObjectDN', 'manager', 'extensionattribute8')

    Logger $LogFileWithPath "Querying $DomainName for user account attributes and exporting to csv file $csvFileWithPath..."
    powershell -Command {
        Param ([string]$domainControlConnector, [string]$csvOutFile, [string]$DomainName, [String[]]$domainUserProperties)
        $domain = "LDAP://$domainControlConnector"

        Write-Host "Searching Users Properties for domain $DomainNamein in AD..."
        $adDomain = New-Object System.DirectoryServices.DirectoryEntry($domain)
        $adSearcher = New-Object System.DirectoryServices.DirectorySearcher($adDomain)
        $adSearcher.Filter = '(objectCategory=User)'
        $adSearcher.PageSize=1000
        $adSearcher.PropertiesToLoad.AddRange($domainUserProperties)
        $userRecords = $adSearcher.FindAll()
        Write-Host "Complete"

        # The AD results are converted to an array of hashtables.
        Write-Host "Exporting User Attributes to table..."
        $userPropertiesTable = @()
        foreach($record in $userRecords) {
            $hashUserProperty = @{}
            foreach($userProperty in $domainUserProperties){
                if ($record.Properties[$userProperty]) {
                    $hashUserProperty.$userProperty = $record.Properties[$userProperty][0]
                } else {
                    $hashUserProperty.$userProperty = $null
                }
            }
            $userPropertiesTable += New-Object PSObject -Property $hashUserProperty
        }
        Write-Host "Complete."

        $listOfBadDateValues = '9223372036854775807', '9223372036854770000', '0'
        $maxDateValue = '12/31/1600 5:00 PM'

        Write-Host "fixing table property titles and values for report"
        #$userPropertiesTable[0] = $userPropertiesTable[0] -replace 'givenname','FirstName'

        $tableFixedValues = $userPropertiesTable | % { 
            if ($_.lastLogonTimestamp) {
                $_.lastLogonTimestamp = ([datetime]::FromFileTime($_.lastLogonTimestamp)).ToString('g')
            }; if (($_.AccountExpires) -and ($listOfBadDateValues -contains $_.AccountExpires)) {
                $_.AccountExpires = $null
            } else {
                if (([datetime]::FromFileTime($_.AccountExpires)).ToString('g') -eq $maxDateValue) {
                    $_.AccountExpires = $null
                } Else {
                    $_.AccountExpires = ([datetime]::FromFileTime($_.AccountExpires)).ToString('g')
                }
            }; if (($_.lastLogon) -and ($listOfBadDateValues -contains $_.lastLogon)) {
                $_.lastLogon = $null
            } else {
                if (([datetime]::FromFileTime($_.lastLogon)).ToString('g') -eq $maxDateValue) {
                    $_.lastLogon = $null
                } Else {
                    $_.lastLogon = ([datetime]::FromFileTime($_.lastLogon)).ToString('g')
                }
            }; if (($_.pwdLastSet) -and ($listOfBadDateValues -contains $_.pwdLastSet)) {
                $_.pwdLastSet = $null
            } else {
                if (([datetime]::FromFileTime($_.pwdLastSet)).ToString('g') -eq $maxDateValue) {
                    $_.pwdLastSet = $null
                } Else {
                    $_.pwdLastSet = ([datetime]::FromFileTime($_.pwdLastSet)).ToString('g')
                }
            };$_}
        Write-Host "Complete"

        Write-Host "Exporting table to csv file $csvOutFile"
        $tableFixedValues | Select-Object $domainUserProperties | Export-Csv $csvOutFile -NoTypeInformation -Force
        Write-Host "Complete"
    } -args $DomainControlConnector, $csvFileWithPath, $DomainName, $domainUserProperties
}

Function Main
{
    CreateQueriedCsvDataSheet

}

Main

注意:我还注意到 memberOf 属性,并未为用户列出所有组...

更新 TheMadTechnician 的回答。

目前正在处理代码片段...

    # The AD results are converted to an array of hashtables.
    Write-Host "Exporting User Attributes to table..."
    $userPropertiesTable = @()
    foreach($record in $userRecords) {
        $hashUserProperty = @{}
        foreach($userProperty in $domainUserProperties){
            if (($userProperty -eq 'objectGUID') -or ($userProperty -eq 'objectSid')) {
                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
    Write-Host "Complete."

好的,这是我的 Switch 示例,用于清理您的 If/Else 块。

$tableFixedValues = Switch($userPropertiesTable){ 
            {$_.lastLogonTimestamp} {$_.lastLogonTimestamp = ([datetime]::FromFileTime($_.lastLogonTimestamp)).ToString('g')}
            {($_.AccountExpires) -and ($listOfBadDateValues -contains $_.AccountExpires) -or ([datetime]::FromFileTime($_.AccountExpires)).ToString('g') -eq $maxDateValue} {$_.AccountExpires = $null}
            {$_.AccountExpires} {([datetime]::FromFileTime($_.AccountExpires)).ToString('g')}
            {$listOfBadDateValues -contains $_.lastLogon -or ([datetime]::FromFileTime($_.lastLogon)).ToString('g') -eq $maxDateValue} {$_.lastLogon = $null}
            {$_.lastLogon} {$_.lastLogon = ([datetime]::FromFileTime($_.lastLogon)).ToString('g')}
            {($_.pwdLastSet) -and ($listOfBadDateValues -contains $_.pwdLastSet) -or (([datetime]::FromFileTime($_.pwdLastSet)).ToString('g') -eq $maxDateValue)} {$_.pwdLastSet = $null}
            {$_.pwdLastSet} {$_.pwdLastSet = ([datetime]::FromFileTime($_.pwdLastSet)).ToString('g')}
            default {$_}
}

这应该能有效地完成与您所做的相同的事情。

现在,对于您的 memberOf 问题,我打赌此更改将为您解决:

$hashUserProperty.$userProperty = ($record.Properties[$userProperty] -join '; ').trim('; ')

这将采用任何集合并使它们成为单个分号连接的项目(更适合导出为 CSV),如果它是一个包含空值的集合,它将在之后删除额外的分号和空格。

CSV 不是包含 memberOf 的好格式,因为它不能很好地管理嵌套数组。这就是我将 memberOf 集合加入单个字符串的原因。如果你想更好地保留格式,你需要迭代 memberOf 中的所有项目,或者,可能更好,使用处理嵌套数组的格式,例如 XML 或 JSON.