首页 > 解决方案 > 输出到 csv 时的 Powershell 奇怪行为

问题描述

将我的 foreach 循环输出到 csv 文件时遇到问题。

我的群组设置如下:

$Groups = "Group1", "Group2", "Group3"

我的代码是:

$results = ForEach ($Group in $Groups) {
        $memberof = get-adgroup $Group | select -expandproperty distinguishedname
        Write-Output $Group
        Get-ADObject -Filter 'memberof -eq $memberof -and (ObjectClass -eq "user" -or ObjectClass -eq "contact")' -properties * | select name, Objectclass, mail
        Write-Output ""
        Write-Output ""
    }

$results | Export-csv  Contacts.csv -NoTypeInformation

问题似乎来自 Write-Output 行,但我不知道为什么。当我在不写入 csv 文件的情况下运行代码时,我得到了预期的结果,例如:

NameOfGroup1
name                        Objectclass mail
----                        ----------- ----
User1                       user        User1@mail.com
User2                       user        User2@mail.com
                                                            #Spaces caused by write-output ""

NameOfGroup2
User1                       user        User1@mail.com
Contact1                    contact     Contact1@externalmail.com

然后,当我运行我的代码写入 csv 文件并write-output $Group注释掉时,我得到了类似的结果。

但是如果我从这个页面的顶部运行我的完整代码,包括write-output $Group,它会像这样:

在此处输入图像描述

我已经弄清楚这些结果代表什么,但我不知道为什么它们会像这样打印出来。

本质上,数字是指组名的长度,因此前 17 位是 17 个字符的组名,然后下面的行数等于该组内的联系人和用户数。每组末尾的 2 个零是write-output ""行的长度。

是什么导致了这种行为?

标签: excelpowershellexport-to-csv

解决方案


以下代码将密切输出您正在尝试的内容。

$results = ForEach ($Group in $Groups) {
        $memberof = get-adgroup $Group | select -expandproperty distinguishedname
        Get-ADUser -Filter "memberof -eq '$memberof' -and (ObjectClass -eq 'user' -or ObjectClass -eq 'contact')" -properties name,ObjectClass,Mail | Select-Object @{n='Group';e={$Group}},name, Objectclass, mail
    [pscustomobject]"" | Select-Object Group,Name,ObjectClass,Mail
    [pscustomobject]"" | Select-Object Group,Name,ObjectClass,Mail
    }

$results | Export-csv  Contacts.csv -NoTypeInformation

解释:

Export-Csv将具有属性的对象或对象数组转换为 CSV 文件。您可以在控制台中看到相同的结果ConvertTo-Csv。属性被转换为列,属性值被放置在它们关联的列下。当您在 中输出字符串时Write-Output $Group,它的属性为Length。要解决此问题,您需要$GroupSelect-Object. 如果你想在你的 CSV 中做空行,那么你应该输出另一个具有所有属性值的对象''

当您在 PowerShell 输出中混合对象时,您会看到意外的结果。您Get-ADObject输出一个自定义对象。您的Write-Output行输出一个字符串。这两种对象类型不共享属性。所以你只能看到数组中第一个对象的属性,它是一个字符串。如果将所有Write-Output语句放在循环的末尾,您将在 CSV 中看到更多属性。请参阅下面的示例,只需颠倒处理对象的顺序,您就会得到不同的结果。

$str = "string"
$obj = [pscustomobject]@{property1 = "value1"; property2 = "value2"}

$str,$obj | convertto-csv -notype
"Length"
"6"

$obj,$str | convertto-csv -notype
"property1","property2"
"value1","value2"
,

注意自定义对象$obj和字符串可用的属性$str

$obj | get-member -Type Properties


   TypeName: System.Management.Automation.PSCustomObject

Name      MemberType   Definition
----      ----------   ----------
property1 NoteProperty string property1=value1
property2 NoteProperty string property2=value2

$str | get-member -Type Properties


   TypeName: System.String

Name   MemberType Definition
----   ---------- ----------
Length Property   int Length {get;}

推荐阅读