可以使用Microsoft Graph PowerShell cmdlet从AdditionalProperties字典中提取信息吗?

vzgqcmou  于 2023-04-12  发布在  Shell
关注(0)|答案(1)|浏览(102)

我正在尝试使用PowerShell Graph cmdlet而不是Azure AD模块cmdlet。使用Azure AD模块,我可以执行以下操作:

# This is what I want:
get-azureadgroupmember -objectid $GroupID | select-object -property displayname, `
    mail, userprincipalname, objectid

DisplayName     Mail                        UserPrincipalName  ObjectId
-----------     ----                        -----------------  --------
John Smith      John.Smith@example.org      jsmith@example.org 4bae8291-6ec3-192b-32ce-dd21869ef784
(...)

# All of these properties are directly accessible in the returned objects:
$res = get-azureadgroupmember -objectid $GroupID
$res[0] | fl -prop *
# Shows long list of directly accessible properties

我正在尝试使用PowerShell Graph来计算等效值:

$res = get-mggroupmember -groupid $GroupID
$res[0] | fl -prop *
# Only properties are DeletedDateTime, Id, and AdditionalProperties

# Want to do something like this, but it doesn't work:
get-mggroupmember -groupid $GroupID | select-object -property id, `
    additionalproperties['displayName'], additionalproperties['mail'], `
    additionalproperties['userPrincipalName']

# This works, but is there a better option???
get-mggroupmember -groupid $GroupID | foreach-object { `
        "{0},{1},{2},{3}" -f $_.id, $_.additionalproperties['displayName'], `
        $_.additionalproperties['mail'], $_.additionalproperties['userPrincipalName']
    }

AdditionalProperties是一个字典(IDictionary),它包含了displayname,mail和userprincipalname。我的想法是可能有一个更好的方法来做到这一点或获取信息。
Get-MgGroupmember中有一些有趣的参数,我不太清楚,包括-ExpandProperty-Property。我试过使用这些参数,但没有任何运气。我想知道是否有一种方法可以使用这些参数来做我想要的事情。
有什么建议?

vxf3dgd4

vxf3dgd41#

给定以下$object,3个属性,其中一个AdditionalPropertiesDictionary<TKey,TValue>

$dict = [Collections.Generic.Dictionary[object, object]]::new()
$dict.Add('displayName', 'placeholder')
$dict.Add('mail', 'placeholder')
$dict.Add('userPrincipalName', 'placeholder')

$object = [pscustomobject]@{
    DeletedDateTime      = 'placeholder'
    Id                   = 'placeholder'
    AdditionalProperties = $dict
}

假设从这个对象中你对IddisplayNamemail感兴趣,你可以使用Select-Object计算属性:

$object | Select-Object @(
    'Id'
    @{
        Name       = 'displayName'
        Expression = { $_.additionalProperties['displayName'] }
    }
    @{
        Name       = 'mail'
        Expression = { $_.additionalProperties['mail'] }
    }
)

然而,当你需要从对象中选择更多的属性值时,这会变得很混乱,在这种情况下,带有循环的PSCustomObject就派上用场了:

$object | ForEach-Object {
    [pscustomobject]@{
        Id          = $_.Id
        displayName = $_.additionalProperties['displayName']
        mail        = $_.additionalProperties['mail']
    }
}

这两种方法都将输出相同的 “flattened” 对象,可以毫无问题地转换为Csv:

  • 作为对象
Id          displayName mail
--          ----------- ----
placeholder placeholder placeholder
  • 作为Csv
"Id","displayName","mail"
"placeholder","placeholder","placeholder"

在这个意义上,你可以使用上面的技术之一构造一个对象数组,例如:

Get-MgGroupMember -GroupId $GroupID | ForEach-Object {
    [pscustomobject]@{
        Id                = $_.id
        displayName       = $_.additionalproperties['displayName']
        mail              = $_.additionalproperties['mail']
        userPrincipalName = $_.additionalproperties['userPrincipalName']
    }
}

如果你正在寻找一种 * 程序化的方法 * 来扁平化对象,你可以从这个例子开始,但是重要的是要注意,这只能处理一个对象的属性只嵌套一次,换句话说,它不能处理递归:

$newObject = [ordered]@{}
foreach($property in $object.PSObject.Properties) {
    if($property.Value -is [Collections.IDictionary]) {
        foreach($addproperty in $property.Value.GetEnumerator()) {
            $newObject[$addproperty.Key] = $addproperty.Value
        }
        continue
    }
    $newObject[$property.Name] = $property.Value
}
[pscustomobject] $newObject

这样的输出会变成一个像这样的扁平对象,它也可以毫无问题地转换为Csv:

DeletedDateTime   : placeholder
Id                : placeholder
displayName       : placeholder
mail              : placeholder
userPrincipalName : placeholder

同样值得注意的是,上面的例子没有处理可能的 * 键冲突 *,如果有2个或更多的属性具有相同的名称,其中一个将覆盖其他属性。
额外的函数,应该与GraphAzureADAz模块的cmdlet返回的对象一起工作。这个函数可以用于扁平化它们的Dictionary2属性。如果属性值实现[IDictionary`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.idictionary?view=net-6.0),它看起来只有一层深,所以不要指望它扁平化任何对象。对于给定的示例应该工作得很好。

function Select-GraphObject {
    [CmdletBinding(PositionalBinding = $false)]
    param(
        [Parameter(Mandatory, ValueFromPipeline, DontShow)]
        [object] $InputObject,

        [Parameter(Position = 0)]
        [SupportsWildcards()]
        [string[]] $Properties = '*'
    )

    begin {
        $firstObject = $true
        $toSelect    = [Collections.Generic.List[object]]::new()
    }
    process {
        if($firstObject) {
            foreach($property in $InputObject.PSObject.Properties) {
                foreach($item in $Properties) {
                    if($property.Value -is [Collections.IDictionary]) {
                        foreach($key in $property.Value.PSBase.Keys) {
                            if($key -like $item -and $key -notin $toSelect.Name) {
                                $toSelect.Add(@{
                                    $key = { $_.($property.Name)[$key] }
                                })
                            }
                        }
                        continue
                    }

                    if($property.Name -like $item -and $property.Name -notin $toSelect) {
                        $toSelect.Add($property.Name)
                    }
                }
            }
            $firstObject = $false
        }

        $out = [ordered]@{}
        foreach($item in $toSelect) {
            if($item -isnot [hashtable]) {
                $out[$item] = $InputObject.$item
                continue
            }
            $enum = $item.GetEnumerator()
            if($enum.MoveNext()) {
                $out[$enum.Current.Key] = $InputObject | & $enum.Current.Value
            }
        }
        [pscustomobject] $out
    }
}

使用上面示例中$object的副本,如果使用默认值-Properties,则示例对象将 flattened

PS /> $object, $object, $object | Select-GraphObject

DeletedDateTime Id          displayName mail        userPrincipalName
--------------- --          ----------- ----        -----------------
placeholder     placeholder placeholder placeholder placeholder
placeholder     placeholder placeholder placeholder placeholder
placeholder     placeholder placeholder placeholder placeholder

或者我们可以过滤特定的属性,甚至是AdditionalProperties属性中的Keys:

PS /> $object, $object, $object | Select-GraphObject Id, disp*, user*

Id          displayName userPrincipalName
--          ----------- -----------------
placeholder placeholder placeholder
placeholder placeholder placeholder
placeholder placeholder placeholder

相关问题