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

使用PowerShell调用CreateRecipient处理Outlook Exchange通讯组时程序挂起

问题:PowerShell调用Outlook COM对象时在CreateRecipient处挂起

极简复现代码

$targetEmail = Read-Host "Enter the email address:"
$outlook = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")
$recipient = $namespace.CreateRecipient($targetEmail)

挂起语句

$recipient = $namespace.CreateRecipient($targetEmail)

已尝试的解决方法

  • 重启Outlook
  • 因Outlook为32位版本,从64位PowerShell切换到32位PowerShell运行代码

补充背景

$targetEmail是Outlook Exchange通讯组地址。已有可正常运行的VBA代码用于获取嵌套通讯组并展开所有成员,现尝试迁移到PowerShell。

可用的VBA代码

Sub SaveDistributionListMembers()
    Dim olApp As Outlook.Application
    Dim olNamespace As Outlook.NameSpace
    Dim recipient As Outlook.recipient
    Dim rootDL As Outlook.AddressEntry
    Dim emailList As Collection
    Dim downloadsPath As String
    Dim fso As Object, outFile As Object
    Dim targetEmail As String
    Dim email As Variant
    
    targetEmail = InputBox("Enter the email address of the distribution list:", "DL Email Input")
    If Trim(targetEmail) = "" Then
        MsgBox "No email address entered. Cancelled.", vbExclamation
        Exit Sub
    End If

    Set olApp = Application
    Set olNamespace = olApp.GetNamespace("MAPI")
    Set recipient = olNamespace.CreateRecipient(targetEmail)

    If recipient.Resolve Then
        Set rootDL = recipient.AddressEntry
        Set emailList = New Collection
        CollectEmailsRecursive rootDL, emailList

        ' Get path to Downloads folder
        downloadsPath = Environ("USERPROFILE") & "\Downloads\DistributionList_Emails.txt"
        
        Set fso = CreateObject("Scripting.FileSystemObject")
        Set outFile = fso.CreateTextFile(downloadsPath, True)

        For Each email In emailList
            outFile.WriteLine email
        Next

        outFile.Close
        MsgBox "Email addresses saved to: " & downloadsPath
    Else
        MsgBox "Could not resolve email address: " & targetEmail
    End If
End Sub

Sub CollectEmailsRecursive(entry As Outlook.AddressEntry, ByRef emailList As Collection)
    Dim members As Outlook.AddressEntries
    Dim member As Outlook.AddressEntry
    Dim i As Long
    Dim smtp As String

    If entry.AddressEntryUserType = olExchangeDistributionListAddressEntry Then
        On Error Resume Next
        Set members = entry.members
        If members Is Nothing Then Exit Sub

        For i = 1 To members.Count
            Set member = members.Item(i)
            If IsDistributionList(member) Then
                ' Recurse
                CollectEmailsRecursive member, emailList
            Else
                smtp = GetSMTPAddress(member)
                If Len(smtp) > 0 Then
                    On Error Resume Next
                    emailList.Add smtp, smtp ' Prevent duplicates using key
                    On Error GoTo 0
                End If
            End If
        Next i
    End If
End Sub

Function IsDistributionList(entry As Outlook.AddressEntry) As Boolean
    IsDistributionList = (entry.AddressEntryUserType = olExchangeDistributionListAddressEntry)
End Function

Function GetSMTPAddress(entry As Outlook.AddressEntry) As String
    Dim exchUser As Outlook.ExchangeUser
    Dim exchDL As Outlook.ExchangeDistributionList

    On Error Resume Next

    If entry.AddressEntryUserType = olExchangeUserAddressEntry Or _
       entry.AddressEntryUserType = olExchangeRemoteUserAddressEntry Then
        Set exchUser = entry.GetExchangeUser
        If Not exchUser Is Nothing Then
            GetSMTPAddress = exchUser.PrimarySmtpAddress
            Exit Function
        End If
    ElseIf entry.AddressEntryUserType = olExchangeDistributionListAddressEntry Then
        Set exchDL = entry.GetExchangeDistributionList
        If Not exchDL Is Nothing Then
            GetSMTPAddress = exchDL.PrimarySmtpAddress
            Exit Function
        End If
    Else
        GetSMTPAddress = entry.Address
    End If
End Function

编写的PowerShell代码

# Prompt for DL email address
$targetEmail = Read-Host "Enter the email address of the distribution list"

# Create Outlook COM objects
$outlook = New-Object -ComObject Outlook.Application
$session = $outlook.Session
$session.Logon("Outlook")
$namespace = $outlook.GetNamespace("MAPI")
$recipient = $namespace.CreateRecipient($targetEmail)

# HashSets to avoid duplicates and circular loops
$emailSet = New-Object System.Collections.Generic.HashSet[string]
$visitedDLs = New-Object System.Collections.Generic.HashSet[string]

# Recursive function to expand DL
function Expand-DL($addressEntry) {
    try {
        if ($addressEntry.AddressEntryUserType -eq 1) {  # Distribution List
            $dlSmtp = Get-SMTPAddress $addressEntry
            if ($dlSmtp -and !$visitedDLs.Contains($dlSmtp)) {
                $visitedDLs.Add($dlSmtp) | Out-Null
                $members = $addressEntry.Members
                if ($members -ne $null) {
                    foreach ($member in $members) {
                        Expand-DL $member
                    }
                }
            }
        } else {
            $smtp = Get-SMTPAddress $addressEntry
            if ($smtp -and !$emailSet.Contains($smtp)) {
                $emailSet.Add($smtp) | Out-Null
            }
        }
    } catch {
        Write-Host "Error expanding entry: $($addressEntry.Name)"
    }
}

# Get SMTP address
function Get-SMTPAddress($entry) {
    try {
        switch ($entry.AddressEntryUserType) {
            0 { return $entry.Address }
            5 {
                $user = $entry.GetExchangeUser()
                if ($user) { return $user.PrimarySmtpAddress }
            }
            1 {
                $dl = $entry.GetExchangeDistributionList()
                if ($dl) { return $dl.PrimarySmtpAddress }
            }
            default { return $entry.Address }
        }
    } catch {
        return $null
    }
}

# Start resolving
if ($recipient.Resolve()) {
    $root = $recipient.AddressEntry
    Expand-DL $root

    # Output path
    $downloads = [Environment]::GetFolderPath("Downloads")
    $outPath = Join-Path $downloads "DistributionList_Emails.txt"
    $emailSet | Sort-Object | Set-Content -Path $outPath -Encoding UTF8

    Write-Host "`nSaved to: $outPath"
} else {
    Write-Host "❌ Could not resolve: $targetEmail"
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:44:57