使用Get-ADUser过滤变量

时间:2019-07-26 15:27:15

标签: powershell active-directory

当前,我正在从SQL数据库中提取电子邮件列表,并将这些电子邮件存储在名为$emaildata的变量中。我正在尝试从Active Directory过滤$emaildata中的所有电子邮件。现在没有错误弹出,但是绝对不是从变量中显示的列表中删除电子邮件。

$ADUsers = Get-AdUser -Filter * -Properties SamAccountName, EmailAddress, Title, LastLogonDate, Name, GivenName, Surname, Company, Department, Country, EmployeeNumber, Enabled | Where {
    ($_.LastLogonDate -ge (Get-Date).AddDays(-30)) -and
    ($_.LastLogonDate -ne $null) -and
    ($_.EmailAddress -ne $null) -and
    ($_.EmployeeNumber -like '1000*') -and
    ($_.Enabled -eq 'True') -and
    ($_.EmailAddress -ne $emaildata)
} | Select GivenName, Surname, EmailAddress, Title
$ADUsers | Export-Csv C:\Lists\MainList.csv -NoTypeInformation

这就是我要尝试的这段代码。

($_.EmailAddress -ne $emaildata)

我一直在寻找很长时间,而我尝试的所有方法都没有用,所以我希望你们能够帮助我。谢谢!

$emaildata中的数据看起来像这样

EmailAddress
------------
test1@test.com
test2@test.com
test3@test.com
test4@test.com
test5@test.com

1 个答案:

答案 0 :(得分:0)

$emailDataStringList = @( $emailData | Foreach-Object { return $_.EmailAddress.Trim() } )

.... | Where-Object { ...
    ($_.EmailAddress -ne $null) -and
    ($_.EmailAddress -ne '') -and
    ($emailDataStringList -notcontains $_.EmailAddress)
}

您的$emailData 不是字符串数组([string[]]),它是具有单个属性的对象数组:EmailAddress(根据您的输出)。有很多选项可以检查$ adUser.EmailAddress是否在$ emailData列表中,但最简单的方法是将对象数组转换为字符串数组:

$emailDataStringList = @( $emailData | Foreach-Object { return $_.EmailAddress.Trim() } )

肯定Enabled有问题:您将其与字符串进行比较,应将其与bool进行比较:

$_.Enabled -eq $true

另外,lastLogonDate可能有问题: 在-and表达式中,应首先检查-ne $null,只有下一步,您才能确定要使用有效值。否则,您可能会遇到$null -comparsionOperator [DateTime]

($_.LastLogonDate -ne $null) -and
($_.LastLogonDate -ge (Get-Date).AddDays(-30)) 

还要设置变量$dateToCheck = [DateTime]::Today.AddDays(-30),然后在Where-Object表达式中比较$_.LastLogonDate -ge $dateToCheck。这样会更快,powershell将LastLogonDate与预定义的值进行比较,并且每次迭代都不会计算新的DateTime

根据Get-ADUser,您可以使用-LDAPFilter '(&(mail=*)(LastLogonTimeStamp=*))'并丢弃-ne $null检查并最大程度地减少内存使用和网络使用。 LDAPFilterFilter是在服务器端处理的

下一步,请注意重要:AD中没有属性LastLogonDate。在Get-AD*中,它是根据LastLogonTimeStamp动态计算的。 LastLogonTimeStamp不会立即复制-它仅存储在DC上,DC仅在另一个DC的值相差超过ms-DS-Logon-Time-Sync-Interval的值(默认14天)时处理用户登录并复制到另一个DC。因此,您应该了解一下:DC上的 LastLogonDate可能已过期14天。See detailed explanation)。如果您确实需要准确的LastLogonDate,则必须检查林中的每个DC。这是一项繁重且耗时的工作。

接下来,强制Get-ADUser$... | Where { ... }为一个数组(使用数组转换括号@())。否则,当这些表达式返回单用户或无用户($null)时,您的代码可能会出现问题。括在@()括号内,可以确保您的变量将是一个包含0、1或多个元素的数组。

接下来,请注意,您可以在此处遇到类似超时的错误,因为Get-AD* cmdlet上存在超时,并且如果管道后的表达式花费大量时间,Get-ADUser将终止,管道将被破坏,并且您遇到错误。

更好的存储Get-ADUser的结果为变量,并在单独的表达式中过滤:

$attributes = @('samaccountname', 'lastlogondate', '.....')    
$ADUsers = @( Get-ADUser -options.... -Properties $attributes )
$ADUsers = @( $ADUsers | Where-object { ... } )
$ADUsers | Select $attributes | Export-Csv -options...

P.S。您的广告或数据库中可能存在空格。在检查位置使用.Trim():

$emailAddresses = @( $emailAddresses | Foreach-Object { return $_.Trim() } ) 
$... | Where { $emailAddresses -contains $_.EmailAddress.Trim()  }

您的代码将如下所示:

$dateToCheck = [DateTime]::Today.AddDays(-30)
$emailDataStringList = @( $emailData | Foreach-Object { return $_.EmailAddress.Trim() } )
$ADUserProperties = @('SamAccountName', 'EmailAddress', 'Title', 'LastLogonDate', 'Name', 'GivenName', 'Surname', 'Company', 'Department', 'Country', 'EmployeeNumber', 'Enabled')
$ADUserList = @( Get-AdUser -LDAPFilter '(&(mail=*)(LastLogonTimeStamp=*)(employeeNumber=1000*))' -Properties $ADUserProperties )
$ADuserList = @( $ADUserList |
    Where-Object { $_.Enabled -eq $True} | # This is simplies check, this should be first
    Where-Object { $_.LastLogonDate -ge $dateToCheck } | 
    Where-Object { $emailDataStringList -notcontains $_.EmailAddress.Trim()}  | # This is hardest cpu-taking check, this should be last
    Select @('GivenName', 'Surname', 'EmailAddress', 'Title')
)
$ADuserList | Export-Csv C:\Lists\MainList.csv -NoTypeInformation

如果您需要更准确的LastLogonDate,则应该从环境中的每个DC 获取ADUsers。像这样:

$DCList = @(get-addomaincontroller -filter *) 
$ADUserList = @( $DCList | ForEach-Object { Get-ADUser -Server $_.DNSName ... -properties @('SID', 'lastlogontimestamp', ...) } )
$ADUserList = @( $ADUserList | Sort-Object -Descending -Property 'lastlogontimestamp' | Sort-Object -Property 'SID' -Unique )

根据MS文档,-Unique占据列表中的第一个对象,因此它应为每个用户获得最准确的LastLogonDate