跨域Get-ADUser-需要帮助

时间:2018-07-10 18:15:56

标签: powershell active-directory

我有以下code

$FilePath_Prefix = "C:\temp\UserLastLogon-" 

function Msg ($Txt="") { 
    Write-Host "$([DateTime]::Now)    $Txt" 
} 

#Cycle each DC and gather user account lastlogon attributes 
$List = @() #Define Array 
(Get-ADDomain).ReplicaDirectoryServers | Sort | % { 
    $DC = $_ 
    Msg "Reading $DC" 
    $List += Get-ADUser -Server $_ -Filter "samaccountname -like '*'" -Properties LastLogon |
             Select samaccountname, lastlogon, @{n='DC';e={$DC}} 
} 

Msg "Sorting for most recent lastlogon" 

$LatestLogOn = @() #Define Array 
$List | Group-Object -Property samaccountname | % { 
    $LatestLogOn += ($_.Group | Sort -prop lastlogon -Descending)[0] 
} 

$List.Clear() 
$FileName = "$FilePath_Prefix$([DateTime]::Now.ToString("yyyyMMdd-HHmmss")).csv" 

try { 
    $LatestLogOn |
        Select samaccountname, lastlogon,
            @{n='lastlogondatetime';e={[datetime]::FromFileTime($_.lastlogon)}}, DC |
        Export-CSV -Path $FileName -NoTypeInformation -Force
    Msg "Exported results. $FileName" 
} catch { 
    Msg "Export Failed. $FileName" 
}

我用它来询问AD用户,以获取我所有域中的最新lastLogon信息。它行之有效,而且运行起来非常快。

现在,我需要在输出中获取更多详细信息,例如givenNameSurname。 达到此目的的最佳方法是什么,因为我不想为这些属性多余地询问我所有的DC。

我在这里的想法是用Get-ADuser -Filter * -Properties givenName, surname, etc..etc创建另一个数组,然后将两个数组绑定在一起。而且我似乎没有做对。有人可以帮忙,或者为我指出正确的方向来完成这项任务。

2 个答案:

答案 0 :(得分:2)

我将获取所有最近的登录信息,并将其保存到哈希表中,该哈希表用于快速查找。我会尝试这样的事情:

$FileName = 'C:\temp\UserLastLogon-{0:yyyyMMdd-HHmmss}.csv' -f [DateTime]::Now
$DCs = (Get-ADDomain).ReplicaDirectoryServers | Sort-Object

# This *may* be more semantically accurate; I don't remember how it works with multiple domains
# $DC = Get-ADDomainController -Filter * | Select-Object -ExpandProperty HostName | Sort-Object

# Create the hash table
$UserLogonInfo = @{}

foreach ($DC in $DCs) {
    Write-Host "Reading logon data from $DC..."
    # Fetch all users that have a LastLogon value from the current DC
    # We specify LastLogon>=1 because some users that never log on have LastLogon of
    # 0 or null, both of which would show up as Jan 1, 1601.
    Get-ADUser -Server $DC -LDAPFilter '(LastLogon>=1)' -Properties LastLogon | ForEach-Object {
        if (!$UserLogonInfo.ContainsKey($_.DistinguishedName)) {
            # If the accountname doesn't exist, add it
            $UserLogonInfo[$_.DistinguishedName] = @{
                LastLogon         = $_.LastLogon
                LastLogonDateTime = ([DateTime]::FromFileTime($_.LastLogon))
                LastLogonDC       = $DC
            }
        }
        elseif (($UserLogonInfo[$_.DistinguishedName].LastLogon -lt $_.LastLogon)) {
            # If the account name exists, update it if it's more recent
            $UserLogonInfo[$_.DistinguishedName] = @{
                LastLogon         = $_.LastLogon
                LastLogonDateTime = ([DateTime]::FromFileTime($_.LastLogon))
                LastLogonDC       = $DC
            }
        }
    }
}

Write-Host "Fetching user data..."
Get-ADUser -Filter * -Properties LastLogon, givenName, surname |
    Select-Object -Property SamAccountName, givenName, surname,
        @{n='LastLogonDateTime';e={$UserLogonInfo[$_.DistinguishedName].LastLogonDateTime}},
        @{n='LastLogonDC';e={$UserLogonInfo[$_.DistinguishedName].LastLogonDC}} |
    Export-CSV -Path $FileName -NoTypeInformation -Force

如果一个帐户的空白LastLogonDateTime和空白的LastLogonDC,则该帐户从未登录过。

使用DistinguishedName代替SamAccountName作为$UserLogonInfo哈希表的键是更正确的方法,如果您要一次查询多个域,这实际上是必需的更改。请注意,我确实指的是多个域,而不仅仅是同一个域中的多个域控制器(尽管有问题标题,我相信您实际上是在这样做)。

在我的域中,拥有3个DC和10,000个用户的整个过程大约需要15秒。

请注意,有种 ton 可能会使LastLogon不准确。可以在没有完整登录或没有交互式登录的情况下进行更新,并且某些登录不会强制更新该字段。如果您确实要跟踪登录,则应该对登录事件使用安全审核。


编辑:

当我们填充$UserLogonInfo时,我们将获取所有帐户,除了根本不具有LogonDate属性的帐户,或者该属性为0或null的帐户。这些都表明没有登录。因此,我们知道,不在$UserLogonInfo哈希表中的任何用户都从未登录过。

如果要在用户帐户从未登录时使用一些特殊值,则应仅使用if语句并检查用户是否在$UserLogonInfo哈希表中:

Get-ADUser -Filter * -Properties LastLogon, givenName, surname |
    Select-Object -Property SamAccountName, givenName, surname,
        @{n = 'LastLogonDateTime'; e = {if ($UserLogonInfo.ContainsKey($_.DistinguishedName)) { $UserLogonInfo[$_.DistinguishedName].LastLogonDateTime } else { 'Never' }}},
        @{n = 'LastLogonDC'; e = {if ($UserLogonInfo.ContainsKey($_.DistinguishedName)) { $UserLogonInfo[$_.DistinguishedName].LastLogonDC } else { 'N/A' }}} |
        Export-CSV -Path $FileName -NoTypeInformation -Force

答案 1 :(得分:0)

问题是,您实际上是在向DC请求该数据,因为默认情况下已返回该数据。所以唯一要添加的是

, givenName, surname

您的Select-Object。通过运行检查

Get-AdUser yourLogin -Properties LastLogon

您将在输出中收到以下属性:DistinguishedName Enabled GivenName LastLogon Name ObjectClass ObjectGUID SamAccountName SID Surname UserPrincipalName

因此,您唯一失去的就是一些记忆。另一种方法是使用

创建另一个数组
$names = Get-ADuser -Filter * | Select-Object SamAccountName, givenName, surname

,然后像这样根据SamAccountName匹配日期:

$LatestLogOn = @() #Define Array 
$List | Group-Object -Property samaccountname | % { 
    $t = ($_.Group | Sort -prop lastlogon -Descending)[0]
    $n = $names | Where-Object samaccountname -eq $t.samaccountname 
    $LatestLogOn += $t | select *, @{n="givenName";e={$n.givenName}}, @{n="surname";e={$n.surname}}
}