PowerShell导出CSV时Enabled列显示System.Object[]异常排查
问题描述
编写PowerShell脚本用于审计导入的CSV文件,最终导出新增字段的完成版CSV:新增列用于标识CSV内的用户是否存在于AD中,若存在则标注对应账户是否为启用状态。
原始脚本代码如下:
#CSV file to have header of "Employee" with First and Last name in each row Echo "CSV file to import must be in c:\temp folder location with header of "Employee"" $csvlocate = (Read-Host -Prompt "CSV File to import (enter in like filename.csv and make sure file is in c:\temp folder)") $csvEmployees = Import-Csv -path C:\temp\$csvlocate.csv $adUsers = Get-AdUser -Filter * foreach ($Employee in $csvEmployees) { $Found = $adUsers | Where-Object { ($_.GivenName -eq $Employee.givenName) -and ($_.Surname -eq $Employee.surName) } if ($Found) { "In AD $($Employee.givenName) $($Employee.surName)." $Employee | Add-Member -Name InAD -Value $true -MemberType NoteProperty $Employee | Add-Member -Name Enabled -Value $Found.Enabled -MemberType NoteProperty } else { "Not in AD $($Employee.givenName) $($Employee.surName)." $Employee | Add-Member -Name InAD -Value $false -MemberType NoteProperty $Employee | Add-Member -Name Enabled -Value $false -MemberType NoteProperty } } $csvEmployeesNotInAd = $csvEmployees.foreach{ $employee = @{ 'CSVName' = $_.Name 'InAD' = $false } if ($_.Name -in $adUsers.Name) { $employee.InAD = $true } [pscustomobject]$employee } $csvEmployees | Export-Csv -Path C:\temp\$csvlocate.completed.csv -NoTypeInformation -Force
执行脚本后导出的CSV文件中,Enabled列所有内容均显示为System.Object[]。
问题原因
Get-AdUsercmdlet 默认返回的属性集不包含Enabled字段,未显式指定返回属性时,访问对象的Enabled成员会得到空数组值。Export-Csv序列化对象时会对非基础类型调用默认ToString()方法,数组类型的默认ToString()返回值就是固定字符串System.Object[],这是触发该问题的核心原因。- 现有匹配逻辑未限制返回结果数量,若AD中存在多个GivenName、Surname完全相同的用户,
$Found变量会存储用户对象数组,此时访问$Found.Enabled会得到所有匹配用户的Enabled属性组成的数组,序列化后同样会显示为System.Object[]。 - 脚本中定义的
$csvEmployeesNotInAd代码块未被后续导出逻辑调用,属于无效冗余代码,会额外消耗执行性能,不直接触发当前报错。 - 原始脚本的文件路径逻辑存在缺陷:提示用户输入带
.csv后缀的文件名,但导入路径又额外拼接了.csv后缀,会触发文件找不到的报错。
修复方案
调整AD查询逻辑显式拉取需要的属性,增加单结果匹配限制,修正路径问题,删除冗余代码,修复后完整脚本如下:
# 提示导入文件规则 Write-Host "CSV file to import must be stored in c:\temp, with column headers including givenName and surName" $csvlocate = Read-Host -Prompt "Enter full CSV filename (e.g. employeelist.csv, ensure file is saved in c:\temp)" $csvEmployees = Import-Csv -Path "C:\temp\$csvlocate" # 显式指定查询返回所需属性,避免默认属性集缺失字段 $adUsers = Get-AdUser -Filter * -Properties GivenName, Surname, Enabled foreach ($Employee in $csvEmployees) { # 取第一个匹配的AD用户,避免同名多用户返回数组对象 $Found = $adUsers | Where-Object { $_.GivenName -eq $Employee.givenName -and $_.Surname -eq $Employee.surName } | Select-Object -First 1 if ($null -ne $Found) { Write-Host "Found AD account for $($Employee.givenName) $($Employee.surName)." $Employee | Add-Member -Name InAD -Value $true -MemberType NoteProperty # 赋值单用户的布尔类型Enabled属性,确保为单值 $Employee | Add-Member -Name Enabled -Value $Found.Enabled -MemberType NoteProperty } else { Write-Host "No AD account found for $($Employee.givenName) $($Employee.surName)." $Employee | Add-Member -Name InAD -Value $false -MemberType NoteProperty $Employee | Add-Member -Name Enabled -Value $false -MemberType NoteProperty } } # 导出最终结果,自动处理文件名后缀避免重复 $exportPath = "C:\temp\$($csvlocate.Replace('.csv','')).completed.csv" $csvEmployees | Export-Csv -Path $exportPath -NoTypeInformation -Force
优化提示:如果域内AD用户总量超过1000,不建议拉取全量AD用户到本地匹配,可以将循环内逻辑改为按用户名单次查询AD,大幅降低内存占用和执行耗时。
内容的提问来源于stack exchange,提问作者MatthewS
相关产品推荐
相关产品推荐

