两个不同大小的对象和 $null

Two objects of different sizes and $null

我下面的代码适用于每个实例,除非一个对象是 $null 而另一个对象有一个项目。当这种情况发生时,输出变成 1 个字母,就像它正在索引一样,我不确定为什么。 如何将这两个对象结合起来制作最终报告?

$ADGroups = Get-ADPrincipalGroupMembership -Identity $UserSam | Select-Object distinguishedName, name | Where-Object { ($_.distinguishedName -ne 'CN=Domain Users,CN=Users,DC=com') }

#record AD groups
$ADResult = @()
if ($null -eq $ADGroups) {
    Write-Warning "No AD Groups"
    $ADResult = [PSCustomObject]@{ 
        ADGroups                  = @()
        ADGroupsdistinguishedName = @()
    }
}
Else {
    $ADResult = $ADGroups | ForEach-Object {
        [PSCustomObject]@{
            ADGroups                  = $_.name
            ADGroupsdistinguishedName = $_.distinguishedName
        }
    }
}

#============= Now Google, get user groups and record
$GoogleGroups = gam print groups member $email members managers owners | ConvertFrom-Csv

# Record Google Groups
$GResult = @()
If ($null -eq $GoogleGroups) {
    Write-Warning "No Google Groups"
    $GResult = [PSCustomObject]@{
        GoogleGroups = @()
        Role         = @()
    }
}
Else {
    $group = $null
    $GResult = ForEach ($group in $GoogleGroups) {
        #this records what role the user had in the group(s)
        $GoogleMember = gam print group-members group $group.email members | ConvertFrom-Csv | Select-Object -ExpandProperty email
        $Role = $null
        If ( $GoogleMember -contains $EMAIL) {
            $Role = 'Member'
        }
        Else {
            $GoogleManager = gam print group-members group $group.email managers | ConvertFrom-Csv | Select-Object -ExpandProperty email
            If ($GoogleManager -contains $EMAIL) {
                $Role = 'Manager'
            }
            Else {
                $Role = 'Owner'
            }
        }
        [PSCustomObject]@{
            GoogleGroups = $group.email
            Role         = $role
        }
        $group = $null
    }
}

# ---------now report that will be dropped off at end
[int]$max = $ADResult.count
if ([int]$GResult.count -gt $max) { [int]$max = $GResult.count }

If ($max -eq 1 -or $max -eq 0) {
    $Result = [PSCustomObject]@{ 
        PrimaryEmail                 = $email
        Title                        = $UserInfo.title
        Department                   = $UserInfo.Department
        Manager                      = $Manager
        ADGroupName                  = $ADResult.ADGroups
        ADGroupNameDistinguishedName = $ADResult.ADGroupsdistinguishedName
        GoogleGroup                  = $GResult.GoogleGroups
        Role                         = $GResult.role
        DateOfSeparation             = (Get-Date).ToString("yyyy_MM_dd")
        UserDistinguishedName        = $UserInfo.distinguishedName
        UserOU                       = $UserInfo.Ou
        PrimaryGroup                 = $UserInfo.primaryGroup.Split('=').Split(',')
    }
}
Else {
    $Result = for ( $i = 0; $i -lt $max; $i++) {
        [PSCustomObject]@{ 
            PrimaryEmail                 = $email
            Title                        = $UserInfo.title
            Department                   = $UserInfo.Department
            ADGroupName                  = $ADResult.ADGroups[$i]
            ADGroupNameDistinguishedName = $ADResult.ADGroupsdistinguishedName[$i]
            GoogleGroup                  = $GResult.GoogleGroups[$i]
            Role                         = $GResult.role[$i]
            DateOfSeparation             = (Get-Date).ToString("yyyy_MM_dd")
            UserDistinguishedName        = $UserInfo.distinguishedName
            UserOU                       = $UserInfo.Ou
            PrimaryGroup                 = $UserInfo.primaryGroup.Split('=').Split(',')[$i]
        }
    }
}


$Result | Export-Csv 'C:\temp\Groups.csv' -NoTypeInformation

按照您的问题的抽象描述:

您在 PowerShell 中看到不幸的不对称

  • 管道中,一个[string]实例被认为是一个单独的对象.

    PS> ('foo' | Measure-Object).Count
    1
    
  • 关于索引,被认为是一个字符数组.

    PS> 'foo'[0]
    f
    

捕获 PowerShell pipeline 输出的一般特征是 如果命令 situationally 只输出一个单个对象,该对象被捕获原样,而两个或更多输出对象导致常规 PowerShell array,类型为 [object[]].

  • 通常,这不是问题,因为 PowerShell 对标量和集合的统一处理允许您甚至索引到 标量(单个对象),即隐式处理单个对象就好像它是单个元素数组:

    PS> (Write-Output 42, 43)[0]
    42
    
    PS> (Write-Output 42)[0]
    42  # still OK, even though only *one* object was output; same as: (42)[0]
    
  • 但是,使用单个 [string] 实例作为输出会出现问题,原因如下:

    PS> (Write-Output 'foo', 'bar')[0]
    foo # OK
    
    PS> (Write-Output 'foo')[0]
    f   # !! Indexing into a *single string* treats it as *character array*
    

同样适用于通过 member-access enumeration, 返回的值:

PS> (Get-Item $HOME, /).FullName[0]
C:\Users\Jdoe

PS> (Get-Item $HOME).FullName[0]
C # !! Indexing into a *single string* treats it as *character array*

解决方法

  • 将感兴趣的命令包含在 @(...)array-subexpression operator 中,以确保其输出始终被视为 数组 .

    PS> @(Write-Output 'foo')[0]
    foo # OK
    
  • 或者,在 变量 中捕获命令的输出时,将该变量类型限制为 [array](与 [object[]] 相同) 或 强类型 数组,[string[]]:

    PS> [array] $output = Write-Output 'foo'; $output[0]
    foo # OK