我有以下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信息。它行之有效,而且运行起来非常快。
现在,我需要在输出中获取更多详细信息,例如givenName
和Surname
。
达到此目的的最佳方法是什么,因为我不想为这些属性多余地询问我所有的DC。
我在这里的想法是用Get-ADuser -Filter * -Properties givenName, surname, etc..etc
创建另一个数组,然后将两个数组绑定在一起。而且我似乎没有做对。有人可以帮忙,或者为我指出正确的方向来完成这项任务。
答案 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}}
}