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

无法移除用户已分配M365许可证 PowerShell脚本执行无效问题

故障根因

原脚本存在4个核心逻辑bug,导致执行无报错但许可证未移除:

  • 用户查询失败后流程未中断:Get-AzureADUser查询用户抛出"找不到用户"错误进入catch块后,仅打印错误信息,没有终止后续逻辑。此时$user变量为空值,后续取$user.AssignedLicenses得到空数组,直接触发"无许可证、跳过移除"分支,全程无报错但未执行任何实际操作。
  • 许可证移除列表初始化异常:Microsoft.Open.AzureAD.Model.AssignedLicenses对象的RemoveLicenses属性默认值为$null,直接对其执行+=操作添加许可证ID会出现类型不匹配问题,最终传给接口的移除许可证列表为空,接口不会执行任何变更。
  • 错误捕获逻辑兼容性差:对组继承许可证的错误判断使用完全文本匹配,不同版本Azure AD模块返回的错误文案存在表述、标点差异,会导致错误捕获失效。
  • 流程控制语句误用:原脚本在非循环的process块中使用continue,非管道场景下会触发非预期的流程跳转,导致后续代码不执行。
修复后完整脚本
function Remove-License {
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
    param (
        [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [string]$UserPrincipalName
    )
    
    process {
        if ($PSCmdlet.ShouldProcess([string]$UserPrincipalName, "Remove all directly assigned licenses")) {
            # 查询用户,失败直接终止当前流程
            try {
                $user = Get-AzureADUser -ObjectId $UserPrincipalName -ErrorAction Stop
            }
            catch {
                Write-Host "Error: no user $($UserPrincipalName) is found" -ForegroundColor Red
                return
            }
            
            # 校验许可证列表
            $SKUs = @($user.AssignedLicenses)
            if (-not $SKUs -or $SKUs.Count -eq 0) {
                Write-Verbose "No directly assigned licenses found for user $($UserPrincipalName), skipping license removal process..."
                return
            }
            
            # 初始化许可证移除对象,先给RemoveLicenses赋值空数组避免类型错误
            $userLicenses = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicenses
            $userLicenses.RemoveLicenses = @()
            foreach ($SKU in $SKUs) {
                $userLicenses.RemoveLicenses += $SKU.SkuId
            }
            
            Write-Verbose "Removing license(s) with SkuId: $($userLicenses.RemoveLicenses -join ", ") "
            try {
                $paramSetAzureADUserLicense = @{
                    ObjectId         = $user.ObjectId
                    AssignedLicenses = $userLicenses
                    ErrorAction      = 'Stop'
                }
                Set-AzureADUserLicense @paramSetAzureADUserLicense
                Write-Host "Successfully removed all directly assigned licenses for user $UserPrincipalName" -ForegroundColor Green
            }
            catch {
                # 用关键词匹配兼容不同模块版本的组继承许可证错误
                if ($_.Exception.Message -match "inherited from a group membership") {
                    Write-Warning "User $UserPrincipalName has licenses assigned via group-based licensing, these licenses cannot be removed directly from the user object. Please adjust the group license assignment rules to remove these licenses."
                    return
                }
                else {
                    Write-Error "Failed to remove licenses for user $UserPrincipalName :`n$_"
                    return
                }
            }
        }
    }
}

# 调用示例:替换为目标用户实际UPN
Remove-License -UserPrincipalName 'User.Name@domain.com' -Verbose
使用说明
  • 执行脚本前需先安装Azure AD模块并完成租户登录:依次执行Install-Module AzureAD -Scope CurrentUser、Connect-AzureAD,使用拥有许可证管理权限的全局管理员/用户管理员账号登录。
  • 可先添加-WhatIf参数执行预演,不会实际修改用户许可证配置,可提前确认操作范围:Remove-License -UserPrincipalName 'User.Name@domain.com' -WhatIf -Verbose
  • 脚本仅能移除直接分配给用户的许可证,通过AAD组基于组许可分配的继承许可证无法通过用户层接口移除,需调整对应组的许可分配规则。

内容的提问来源于stack exchange,提问作者Senior Systems Engineer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 05:09:17