适用于 PowerShell 5.1 及以上版本,需要 Microsoft Graph PowerShell SDK 或 Azure AD 租户
Microsoft Graph API 是微软云服务的统一入口——Azure AD(Entra ID)用户管理、Teams 消息、SharePoint 文件、Outlook 邮件、OneDrive,几乎所有 Microsoft 365 服务都通过 Graph API 暴露。Microsoft Graph PowerShell SDK 封装了这些 API,让运维人员可以用 PowerShell 管理整个 Microsoft 365 生态。
本文将讲解 Microsoft Graph PowerShell SDK 的高级用法和实用的管理场景。
连接与认证 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Connect-MgGraph -Scopes "User.Read.All" , "Group.Read.All" , "Directory.Read.All" Get-MgContext | Format-List
执行结果示例:
1 2 3 4 5 6 ClientId : 14d82eec-204b-4c2f-b7e8-296a70dab67e TenantId : contoso.onmicrosoft.com Scopes : {User.Read.All, Group.Read.All, Directory.Read.All} AuthType : DelegatedTokenCredentialType : InteractiveBrowserAccount : admin@contoso .onmicrosoft.com
用户管理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 $users = Get-MgUser -All -Property DisplayName, Mail, JobTitle, Department, AccountEnabledWrite-Host "总用户数:$ ($users .Count)" -ForegroundColor Cyan$engineering = $users | Where-Object { $_ .Department -eq "工程部" }Write-Host "工程部人数:$ ($engineering .Count)" $targetUser = Get-MgUser -Filter "DisplayName eq '张三'" -Property DisplayName, Mail, JobTitle$targetUser | Format-List DisplayName, Mail, JobTitle$newUser = @ { AccountEnabled = $true DisplayName = "测试用户" MailNickname = "testuser" UserPrincipalName = "testuser@contoso.onmicrosoft.com" PasswordProfile = @ { Password = "TempP@ss123!" ForceChangePasswordNextSignIn = $true } } $disabledUsers = Get-MgUser -Filter "AccountEnabled eq false" -Property DisplayName, MailWrite-Host "`n已禁用账户:$ ($disabledUsers .Count) 个" -ForegroundColor Yellow$disabledUsers | Select-Object DisplayName, Mail | Format-Table -AutoSize $signIns = Get-MgAuditLogSignIn -Top 5 -Filter "UserId eq '$ ($targetUser .Id)'" $signIns | Select-Object CreatedDateTime, AppDisplayName, ClientAppUsed, Status | Format-Table -AutoSize
执行结果示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 . ----------- ---- . . --------------- -------------- ------------- ------ - - - -
组与许可证管理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 $groups = Get-MgGroup -All -Property DisplayName, Description, GroupTypes, MembershipRuleWrite-Host "总组数:$ ($groups .Count)" -ForegroundColor Cyan$securityGroups = $groups | Where-Object { $_ .GroupTypes -notcontains "Unified" }Write-Host "安全组:$ ($securityGroups .Count) 个" $m365Groups = $groups | Where-Object { $_ .GroupTypes -contains "Unified" }Write-Host "M365 组:$ ($m365Groups .Count) 个" $groupName = "工程部-开发组" $group = Get-MgGroup -Filter "DisplayName eq '$groupName '" $members = Get-MgGroupMember -GroupId $group .Id -All Write-Host "`n$groupName 成员($ ($members .Count) 人):" -ForegroundColor Cyan$members | ForEach-Object { $user = Get-MgUser -UserId $_ .Id -Property DisplayName, Mail Write-Host " $ ($user .DisplayName) - $ ($user .Mail)" } $subscribedSkus = Get-MgSubscribedSku Write-Host "`n许可证概览:" -ForegroundColor Cyanforeach ($sku in $subscribedSkus ) { $available = $sku .PrepaidUnits.Enabled - $sku .ConsumedUnits Write-Host " $ ($sku .SkuPartNumber):已购买 $ ($sku .PrepaidUnits.Enabled),已分配 $ ($sku .ConsumedUnits),可用 $available " } function Add-UsersToGroup { param ( [string ]$GroupName , [string []]$UserEmails ) $group = Get-MgGroup -Filter "DisplayName eq '$GroupName '" if (-not $group ) { Write-Host "组不存在:$GroupName " -ForegroundColor Red return } foreach ($email in $UserEmails ) { $user = Get-MgUser -Filter "Mail eq '$email '" -Property Id, DisplayName if ($user ) { try { New-MgGroupMember -GroupId $group .Id -DirectoryObjectId $user .Id Write-Host "已添加:$ ($user .DisplayName) => $GroupName " -ForegroundColor Green } catch { Write-Host "添加失败:$email - $ ($_ .Exception.Message)" -ForegroundColor Yellow } } } }
执行结果示例:
1 2 3 4 5 6 7 8 9 10 11 12 总组数:89 安全组:65 个 M365 组:24 个 工程部-开发组 成员(15 人): 张三 - zhangsan@ contoso.com 李四 - lisi@ contoso.com 王五 - wangwu@ contoso.com 许可证概览: ENTERPRISEPACK:已购买 500 ,已分配 245 ,可用 255 EMS_E5:已购买 200 ,已分配 180 ,可用 20
设备与条件访问 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 $devices = Get-MgDevice -All -Property DisplayName, OperatingSystem, ApproximateLastSignInDateTime, TrustTypeWrite-Host "已注册设备:$ ($devices .Count)" -ForegroundColor Cyan$deviceSummary = $devices | Group-Object OperatingSystem | Sort-Object Count -Descending $deviceSummary | ForEach-Object { Write-Host " $ ($_ .Name):$ ($_ .Count) 台" -ForegroundColor Cyan } $cutoff = (Get-Date ).AddDays(-90 )$staleDevices = $devices | Where-Object { $_ .ApproximateLastSignInDateTime -and [datetime ]$_ .ApproximateLastSignInDateTime -lt $cutoff } Write-Host "`n过期设备(90天未活跃):$ ($staleDevices .Count) 台" -ForegroundColor Yellow$caPolicies = Get-MgIdentityConditionalAccessPolicy Write-Host "`n条件访问策略:$ ($caPolicies .Count) 条" -ForegroundColor Cyan$caPolicies | Select-Object DisplayName, State | Format-Table -AutoSize function Export-MgUserReport { param ([string ]$OutputPath = "C:\Reports\users.csv" ) $users = Get-MgUser -All -Property DisplayName, Mail, Department, JobTitle, AccountEnabled, CreatedDateTime $report = $users | Select-Object DisplayName, Mail, Department, JobTitle, @ {N='Enabled' ; E={$_ .AccountEnabled}}, @ {N='Created' ; E={$_ .CreatedDateTime.ToString('yyyy-MM-dd' )}} $report | Export-Csv $OutputPath -NoTypeInformation -Encoding UTF8 Write-Host "用户报告已导出:$OutputPath ($ ($users .Count) 条)" -ForegroundColor Green } Export-MgUserReport
执行结果示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ----------- ----- - .
注意事项
权限范围 :连接时指定最小必要权限,避免使用过大的权限范围
分页 :大量数据需要使用 -All 参数或手动处理分页,默认只返回部分结果
速率限制 :Graph API 有请求频率限制,批量操作时添加 Start-Sleep 避免触发限流
应用权限 vs 委托权限 :自动化脚本使用应用权限(证书认证),交互操作使用委托权限(用户登录)
Consent :某些权限需要管理员同意(Admin Consent),首次使用时需要授权
模块更新 :Graph API 更新频繁,定期更新 SDK 模块:Update-Module Microsoft.Graph