You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MSOnline模块扩展PowerShell用户授权信息脚本时出现执行停滞问题求助

解决MSOnline脚本获取用户组信息时的性能停滞问题

嘿,我来帮你分析下这个脚本卡住的核心原因——这绝对是性能效率问题,典型的反向遍历导致的资源浪费!

问题根源

你当前的组查询逻辑是:

  • 对每个用户,先遍历租户内所有的组
  • 对每个组调用Get-MsolGroupMember远程API,检查当前用户是否是该组成员

假设你的租户有1000个组、500个授权用户,那就要执行500×1000=50万次API调用,每次远程请求都有延迟,累积起来直接让脚本卡在循环里,看起来毫无进展。虽然单条调试能出结果,但批量执行时,重复请求的开销直接拖垮了脚本运行效率。

优化解决方案

核心思路是预缓存所有组与成员的映射关系,只执行一次组和成员的拉取,之后每个用户直接从缓存中读取所属组,避免重复调用API。

修改后的完整脚本

# 第一步:一次性获取所有组及其成员,建立用户邮箱到组名的哈希表缓存(仅执行一次)
$groupMemberCache = @{}
Get-MsolGroup -All | ForEach-Object {
    $currentGroupName = $_.DisplayName
    # 获取当前组的所有成员
    Get-MsolGroupMember -All -GroupObjectId $_.ObjectId | ForEach-Object {
        if ($_.EmailAddress) {
            # 如果缓存中没有该用户的条目,初始化一个空数组
            if (-not $groupMemberCache.ContainsKey($_.EmailAddress)) {
                $groupMemberCache[$_.EmailAddress] = @()
            }
            # 将当前组名添加到该用户的组列表中
            $groupMemberCache[$_.EmailAddress] += $currentGroupName
        }
    }
}

# 第二步:遍历用户并生成结果(复用缓存,无需重复查组)
$result = foreach($domain in $domains){
    $users = Get-MsolUser -All | Where-Object {$_.IsLicensed -eq $true -and $_.UserPrincipalName -match "$domain"}
    foreach ($i in $users){
        $licenses = $i.Licenses
        $licenseArray = $licenses | ForEach-Object {$_.AccountSkuId}
        # 注意:你原脚本中的$licensear = Friendlyname是笔误,需补全AccountSkuId转友好名称的逻辑
        $licenseString = $licenseAr -join ", "
        
        # 从缓存中快速获取当前用户的所属组
        $userGroups = if ($groupMemberCache.ContainsKey($i.UserPrincipalName)) {
            $groupMemberCache[$i.UserPrincipalName] -join ", "
        } else {
            "无所属组"
        }

        New-Object PSObject -Property @{
            Displayname = $i.Displayname
            Userprincipalname = $i.userprincipalname
            UPN = ($i.userprincipalname -Split '@')[1]
            Licenses = $licenseString
            Groups = $userGroups
        }
    }
}

额外注意事项

  1. 原脚本中$licensear = Friendlyname是明显的笔误,记得补全将AccountSkuId转换为友好名称的逻辑,否则Licenses字段会为空。
  2. 如果租户的组成员规模极大,缓存阶段可能会有短暂的等待,但这是一次性开销,后续用户处理会非常顺畅。
  3. 若用户没有邮箱(比如某些服务账号),缓存时会跳过这类用户,避免无效条目。

内容的提问来源于stack exchange,提问作者Matthew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 23:27:47