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

如何提速获取12k+ M365用户信息的PowerShell脚本?

提速M365用户信息导出的方案

你的PowerShell脚本处理12000名用户耗时数小时,核心瓶颈在循环内逐个调用Get-Mailbox——每调用一次都是一次远程请求,12000次请求累积下来拖慢了整体速度。以下是两种可行的提速方案:

一、优化现有PowerShell脚本

1. 批量获取所有邮箱,用哈希表关联

把Get-Mailbox的调用从循环内移到外部,一次性获取所有邮箱数据,再通过哈希表建立用户UPN到邮箱对象的映射,循环时直接从哈希表取值,避免重复远程请求:

# 批量获取所有AAD用户
$allUsers = Get-AzureADUser -All $true

# 批量获取所有邮箱,建立UPN到邮箱的哈希映射
$allMailboxes = Get-Mailbox -ResultSize Unlimited
$mailboxMap = @{}
foreach ($mbx in $allMailboxes) {
    $mailboxMap[$mbx.UserPrincipalName] = $mbx
}

$outputPath = 'c:\blahblahpath\M365users.csv'
# 先清空文件
Clear-Content -Path $outputPath -ErrorAction SilentlyContinue

# 收集所有用户对象,最后一次性导出
$outputObjects = foreach ($user in $allUsers) {
    # 从哈希表取对应邮箱,无则为空
    $mbx = $mailboxMap[$user.UserPrincipalName]

    $Extension_Attributes = New-Object Psobject -Property $user.ExtensionProperty 

    [pscustomobject] @{
        "UserPrincipalName" = $user.UserPrincipalName
        "GivenName" = $user.GivenName
        "Surname" = $user.Surname
        "M3-DisplayName" = $user.DisplayName
        "JobTitle" = $user.JobTitle
        "Department" = $user.Department
        "CompanyName" = $user.CompanyName
        "M3-Mail" = $user.mail
        "M3-OtherMails" = $user.OtherMails[0]
        "ForwardingSmtpAddress" = $mbx.ForwardingSmtpAddress
        "ExternalEmailAddress" = $mbx.ExternalEmailAddress
        "Aliases" = $mbx.EmailAddresses
        "DeliverToMailboxAndForward" = $mbx.DeliverToMailboxAndForward
        "TelephoneNumber" = $user.TelephoneNumber
        "PhysicalDeliveryOfficeName" = $user.PhysicalDeliveryOfficeName
        "PreferredLanguage" = $user.PreferredLanguage
        "MailNickName" = $user.MailNickName 
        "StreetAddress" = $user.StreetAddress
        "City" = $user.City
        "State" = $user.State
        "PostalCode" = $user.PostalCode
        "Country" = $user.Country
        "UsageLocation" = $user.UsageLocation
        "Mobile" = $user.Mobile 
        "UserType" = $user.UserType
        "AccountEnabled" = $user.AccountEnabled
        "LastLogon" = $user.LastLogon
        "BlockCredential" = $user.BlockCredential
        "AssignedLicenses" = $user.AssignedLicenses
        "Created" = $Extension_Attributes.createdDateTime 
        "MemberNumber" = $Extension_Attributes.EmployeeID
        "TokenExp" = $user.RefreshTokensValidFromDateTime
        "OLDMemNumExt" = $Extension_Attributes.extension_60a1274a0a9d4344bd172d81b06d0f50_MemberNumber
        "Source" = $Extension_Attributes.extension_06f8dc5952b048a1879af4e793844173_Source
        "M3-MemType" = $Extension_Attributes.extension_01816427922e40c9b55cf4364bc171ce_MemType
        "M3-Status" = $Extension_Attributes.extension_01816427922e40c9b55cf4364bc171ce_Status
        "EmailTeams" = $Extension_Attributes.extension_01816427922e40c9b55cf4364bc171ce_EmailTeams
        "M3-EmailCC" = $Extension_Attributes.extension_01816427922e40c9b55cf4364bc171ce_EmailCC
        "M3-EmailPri" = $Extension_Attributes.extension_01816427922e40c9b55cf4364bc171ce_EmailPri
        "Cert" = $Extension_Attributes.extension_01816427922e40c9b55cf4364bc171ce_Cert
        "M3-ExpDate" = $Extension_Attributes.extension_01816427922e40c9b55cf4364bc171ce_ExpDate
        "WGTitle" = $Extension_Attributes.extension_01816427922e40c9b55cf4364bc171ce_WGTitle
        "ChapTitle" = $Extension_Attributes.extension_01816427922e40c9b55cf4364bc171ce_ChapTitle
        "OtherTitle" = $Extension_Attributes.extension_01816427922e40c9b55cf4364bc171ce_LdrTitle
        "Othercodes" = $extension_Attributes.extension_11b052b5eb8f4c77973a06876d25a6a4_Othercodes
        "ChapCodes" = $extension_Attributes.extension_11b052b5eb8f4c77973a06876d25a6a4_ChapCodes
        "WGcodes" = $extension_Attributes.extension_11b052b5eb8f4c77973a06876d25a6a4_WGcodes
        "Allcodes" = $extension_Attributes.extension_a14f14664c8e457a856d24680b31c9d4_AllCodes
        "Cmems" = $Extension_Attributes.extension_4adef2735ffb4a9dafc9a85188ca512d_Cmems
        "M3-isnet" = $Extension_Attributes.extension_01816427922e40c9b55cf4364bc171ce_IsNet
        "SipProxyAddress" = $user.SipProxyAddress
    }
}

# 一次性导出所有数据到CSV,避免多次打开文件
$outputObjects | Export-Csv -Path $outputPath -NoTypeInformation -Force

2. 额外优化点

  • 删除原脚本中无实际作用的$path -replace ' ', ' '`代码行。
  • 修正原脚本未定义的$keepinmbx变量,替换为邮箱对象的DeliverToMailboxAndForward属性。
  • 修复Allcodes字段属性名的多余空格问题。

二、用Python调用Microsoft Graph API实现更快获取

如果想进一步提速,可以用Python调用Microsoft Graph API,它支持批量请求和更高效的数据查询:

核心思路

  1. 通过Graph API一次性获取所有AAD用户的所需属性(包括扩展属性)。
  2. 再一次性获取所有邮箱的关键字段。
  3. 用Python字典建立用户UPN到邮箱数据的映射,合并后导出CSV。

示例代码框架

import csv
from msgraph.core import GraphClient

# 初始化Graph客户端(需提前完成身份验证,比如Client Credentials流)
client = GraphClient(credentials=your_credentials)

# 获取所有AAD用户,包含所需属性和扩展属性
users_response = client.get('/users?$select=userPrincipalName,givenName,surname,displayName,jobTitle,department,companyName,mail,otherMails,telephoneNumber,physicalDeliveryOfficeName,preferredLanguage,mailNickname,streetAddress,city,state,postalCode,country,usageLocation,mobile,userType,accountEnabled,lastSignInDateTime,blocked,assignedLicenses,refreshTokensValidFromDateTime,sipProxyAddress&$expand=extensionProperties')
users = users_response.json()['value']

# 获取所有邮箱数据
mailboxes_response = client.get('/users/mailboxes?$select=userPrincipalName,forwardingSmtpAddress,externalEmailAddress,emailAddresses,deliverToMailboxAndForward')
mailboxes = mailboxes_response.json()['value']
mailbox_map = {mbx['userPrincipalName']: mbx for mbx in mailboxes}

# 准备输出数据
output_rows = []
for user in users:
    upn = user['userPrincipalName']
    mbx = mailbox_map.get(upn, {})
    ext_props = user.get('extensionProperties', {})
    row = {
        'UserPrincipalName': upn,
        'GivenName': user.get('givenName'),
        'Surname': user.get('surname'),
        'M3-DisplayName': user.get('displayName'),
        'JobTitle': user.get('jobTitle'),
        'Department': user.get('department'),
        'CompanyName': user.get('companyName'),
        'M3-Mail': user.get('mail'),
        'M3-OtherMails': user.get('otherMails', [])[0] if user.get('otherMails') else None,
        'ForwardingSmtpAddress': mbx.get('forwardingSmtpAddress'),
        'ExternalEmailAddress': mbx.get('externalEmailAddress'),
        'Aliases': ','.join(mbx.get('emailAddresses', [])),
        'DeliverToMailboxAndForward': mbx.get('deliverToMailboxAndForward'),
        # 其他字段按PowerShell脚本的字段顺序填充
        'Created': ext_props.get('createdDateTime'),
        'MemberNumber': ext_props.get('EmployeeID')
    }
    output_rows.append(row)

# 导出到CSV
with open('c:\\blahblahpath\\M365users.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.DictWriter(f, fieldnames=output_rows[0].keys())
    writer.writeheader()
    writer.writerows(output_rows)

优势

  • Graph API的批量查询效率远高于PowerShell逐个调用Cmdlet,尤其针对大规模数据。
  • Python的字典映射和批量写入CSV的速度也比PowerShell循环Append更快。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 10:30:42