【发布时间】:2022-01-27 10:32:05
【问题描述】:
我的目标是转储我们的 AD 组、他们的成员以及这些成员对象是否已启用的 CSV,但我遇到了一个奇怪的(可能是自己造成的)问题,其中 Foreach-Object 循环的行为没想到。
输出几乎有效。它转储一个 CSV 文件。该文件包含每个组的行,填充了正确的组相关数据,以及正确的行数,跟在组成员的数量之后。但是,这些行上的组成员属性会重复,为每个组成员结果反复显示相同的用户数据,显然遵循 Get-ADGroupMember 中最后返回的对象的属性。
为了尝试诊断问题,我添加了Write-Host $GroupMember.Name -ForegroundColor Gray 这一行。这就是我知道 CSV 中的条目是每个组的最后返回结果的方式。令人困惑的是,控制台正确地回显了每个组成员的显示名称。
我假设这里存在某种逻辑错误,但我没有找到它。任何帮助将不胜感激!
clear
Import-Module ActiveDirectory
# CONFIG ========================================
# Plant Number OU to scan. Used in $CSV and in Get-ADComputer's search base.
$PlantNumber = "1234"
# FQDN of DC you want to query against. Used by the Get-AD* commands.
$ServerName = "server.com"
# Output directory for the CSV. Default is [Environment]::GetFolderPath("Desktop"). Used in $CSV. NOTE: If setting up as an automated task, change this to a more sensible place!
$OutputDir = [Environment]::GetFolderPath("Desktop")
# CSV Output string. Default is "$OutputDir\$PlantNumber"+"-ComputersByOS_"+"$(get-date -f yyyy-MM-dd).csv" (+'s used due to underscores in name)
$CSV = "$OutputDir\$PlantNumber"+"GroupMembers_"+"$(get-date -f yyyy-MM-dd).csv"
# Create empty array for storing collated results
$collectionTable = @()
# Get AD groups, return limited properties
Get-AdGroup -filter * -Property Name, SamAccountName, Description, GroupScope -SearchBase "OU=Security Groups,OU=$PlantNumber,OU=Plants,DC=SERVER,DC=COM" -server $ServerName | Select SamAccountName, Description, GroupScope | Foreach-Object {
Write-Host "Querying" $_.SamAccountName "..."
#Initialize $collectionRow, providing the columns we want to collate
$collectionRow = "" | Select GroupName, GroupScope, GroupDesc, MemberObjectClass, MemberName, MemberDisplayName, Enabled
# Populate Group-level collectionRow properties
$collectionRow.GroupName = $_.SamAccountName
$collectionRow.GroupDesc = $_.Description
$collectionRow.GroupScope = $_.GroupScope
# Process group members
Get-ADGroupMember -Identity ($collectionRow.GroupName) -Server $ServerName -Recursive | ForEach-Object {
$GroupMember = $_
# Echo member name to console
Write-Host $GroupMember.Name -ForegroundColor Gray
$collectionRow.MemberName = $GroupMember.SamAccountName
$collectionRow.MemberDisplayName = $GroupMember.name
$collectionRow.MemberObjectClass = $GroupMember.ObjectClass
# If the member object is a user, collect some additional data
If ($collectionRow.MemberObjectClass -eq "user") {
Try {
$collectionRow.Enabled = (Get-ADUser $GroupMember.SamAccountName -Property Enabled -ErrorAction Stop).Enabled
If ($collectionRow.Enabled -eq "TRUE") {$collectionTable += $collectionRow}
}
Catch {
$collectionRow.Enabled = "ERROR"
$collectionTable += $collectionRow
}
}
}
}
Write-Host "`n"
# Attempt to save results to CSV. If an error occurs, alert the user and try again.
$ExportSuccess = 'false'
while ($ExportSuccess -eq 'false') {
Try
{
# Export results to $CSV
$collectionTable| Export-csv $CSV -NoTypeInformation -ErrorAction Stop
# If the above command is successful, the rest of the Try section will execute. If not, Catch is triggered instead.
$ExportSuccess = 'true'
Write-Host "`nProcessing complete. Results output to"$CSV
}
Catch
{
Write-Host "Error writing to"$CSV"!" -ForegroundColor Yellow
Read-Host -Prompt "Ensure the file is not open, then press any key to try again"
}
}
【问题讨论】:
-
....在我看来,这个问题更多地属于code review而不是SO。
-
@Olaf,我认为它不符合他们的发帖规则,所以它可能不适合那里。
-
hmmm ...好的,对我来说,您的代码看起来很混乱。但也许一些一般提示可以帮助你。根据您的 AD 结构,您最终可能会多次查询相同的用户。相反,您可以一次将所有用户收集到一个临时变量中并使用它。对于您的输出,我建议使用
PSCustomObject。
标签: powershell csv foreach