请求修复PowerShell脚本:导出通讯组及嵌套组成员至Excel
修复后的PowerShell脚本及问题说明
问题排查与修复点
- 参数格式错误:原脚本获取嵌套成员时,
Get-DistributionGroupMember的参数拼接错误,-RecipientTypeDetails前缺少空格和参数符号,导致命令无法解析。 - 动态通讯组处理错误:
Get-DistributionGroupMember无法获取动态通讯组成员,需改用Get-Recipient结合动态组的筛选条件来查询。 - 工作表命名非法字符处理:组名称中的
/、\、:、*、?、"、<、>、|等字符是Excel工作表命名的非法字符,需替换为合法字符(如_)。 - 添加错误处理与Excel进程清理:增加
try/catch块捕获异常,确保Excel进程能正常退出,避免残留。 - 可选:支持多层嵌套递归:添加递归函数处理多层嵌套组的导出需求。
修复后的完整脚本
$OutputFile = "DL-Members_$(Get-Date -Format ddMMMyyyy_hhmmss).xlsx" $GroupName = "Test-DistributionList@contoso.com" # 处理Excel工作表非法字符的函数 function Get-ValidSheetName { param([string]$Name) $invalidChars = [IO.Path]::GetInvalidFileNameChars() -join '' $regex = "[{0}]" -f [regex]::Escape($invalidChars) return ($Name -replace $regex, "_").Substring(0, [Math]::Min($Name.Length, 31)) # Excel工作表名最长31字符 } # 递归导出组成员的函数 function Export-GroupMembers { param( [string]$GroupIdentity, [object]$Workbook, [string]$ParentSheetName = $null ) $group = Get-DistributionGroup -Identity $GroupIdentity -ErrorAction Stop $sheetName = Get-ValidSheetName -Name $group.DisplayName $sheet = $Workbook.Sheets.Add() $sheet.Name = $sheetName # 设置表头:将组名作为标题,合并单元格 $sheet.Range("A1:C1").Merge() | Out-Null $sheet.Cells.Item(1,1) = $group.DisplayName $sheet.Cells.Item(1,1).Font.Bold = $true $sheet.Cells.Item(2,1) = "Display Name" $sheet.Cells.Item(2,2) = "Primary Smtp Address" $sheet.Cells.Item(2,3) = "Recipient Type" $row = 3 # 根据组类型获取成员 if ($group.RecipientTypeDetails -eq "DynamicDistributionGroup") { $members = Get-Recipient -RecipientFilter $group.RecipientFilter -ResultSize Unlimited -ErrorAction Stop } else { $members = Get-DistributionGroupMember -Identity $GroupIdentity -RecipientTypeDetails UserMailbox, MailUniversalDistributionGroup, DynamicDistributionGroup, SecurityDistributionGroup -ErrorAction Stop } foreach ($member in $members) { $sheet.Cells.Item($row,1) = $member.DisplayName $sheet.Cells.Item($row,2) = $member.PrimarySmtpAddress $sheet.Cells.Item($row,3) = $member.RecipientTypeDetails $row++ # 如果是组类型,递归导出 if ($member.RecipientTypeDetails -in "MailUniversalDistributionGroup", "DynamicDistributionGroup", "SecurityDistributionGroup") { Export-GroupMembers -GroupIdentity $member.PrimarySmtpAddress -Workbook $Workbook -ParentSheetName $sheetName } } # 自动调整列宽 $sheet.UsedRange.EntireColumn.AutoFit() | Out-Null } try { $Excel = New-Object -ComObject Excel.Application $Excel.Visible = $false # 后台运行Excel $Workbook = $Excel.Workbooks.Add() # 删除默认的空白工作表 foreach ($sheet in $Workbook.Sheets) { if ($sheet.Name -notin ($Workbook.Sheets | Select-Object -Last 1).Name) { $sheet.Delete() } } # 导出顶层组成员 Export-GroupMembers -GroupIdentity $GroupName -Workbook $Workbook # 保存并关闭Excel $Workbook.SaveAs((Join-Path -Path $PWD.Path -ChildPath $OutputFile)) $Excel.Quit() [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel) | Out-Null [System.GC]::Collect() [System.GC]::WaitForPendingFinalizers() Write-Host "成员已成功导出至文件: $OutputFile" -ForegroundColor Green } catch { Write-Host "导出失败: $_" -ForegroundColor Red # 确保Excel进程退出 if ($Excel) { $Excel.Quit() [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel) | Out-Null } }
关键修复说明
- 参数格式修正:将原脚本中错误的
Get-DistributionGroupMember -Identity $Member.PrimarySmtpAddress,RecipientTypeDetails ...修正为正确的参数传递格式,确保命令能正常执行。 - 动态组成员获取:针对动态通讯组,使用
Get-Recipient结合组的RecipientFilter属性来获取符合条件的成员,避免命令报错。 - 工作表名合法性处理:通过
Get-ValidSheetName函数替换非法字符,并限制长度为31(Excel工作表名最大长度),防止命名失败。 - 递归嵌套处理:新增
Export-GroupMembers递归函数,自动处理多层嵌套组的导出,无需手动编写多层循环。 - Excel进程清理:在
try/catch块中确保无论成功还是失败,Excel进程都能正常退出,避免后台残留进程占用资源。 - 优化表头显示:将组名作为工作表的标题(合并单元格),满足你提出的“表头设为嵌套组名称”的需求。
内容的提问来源于stack exchange,提问作者night-fury
相关产品推荐
相关产品推荐

