两个不同大小的对象和 $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
我下面的代码适用于每个实例,除非一个对象是 $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