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

如何用PowerShell 5将共享盘中大量.msg文件转PDF并嵌入附件?

解决MSG转PDF时嵌入附件的问题

我的共享盘中有大量.msg文件需要转换为PDF格式,使用PowerShell 5脚本转换时能完成基础转换,但会遗漏附件,希望将附件嵌入PDF而非保存为单独文件。原脚本如下:

$outlook = New-Object -ComObject Outlook.Application
$word = New-Object -ComObject Word.Application

Get-ChildItem -Path $folderPath -Filter *.msg? | ForEach-Object {

    $msgFullName = $_.FullName
    $docFullName = $msgFullName -replace '\.msg$', '.doc'
    $pdfFullName = $msgFullName -replace '\.msg$', '.pdf'

    $msg = $outlook.CreateItemFromTemplate($msgFullName)
    $msg.SaveAs($docFullName, 4)

    $doc = $word.Documents.Open($docFullName)
    $doc.SaveAs([ref] $pdfFullName, [ref] 17)

    $doc.Close()
 }

解决方案

要实现附件嵌入PDF,需在将DOC转PDF前,把邮件附件插入到Word文档中。修改后的脚本会遍历邮件附件,将每个附件嵌入到文档末尾后再转换为PDF:

$outlook = New-Object -ComObject Outlook.Application
$word = New-Object -ComObject Word.Application
$word.Visible = $false # 后台运行Word,不显示窗口

# 创建临时目录存放附件
$tempDir = Join-Path $env:TEMP "MsgToPdfTemp"
if (-not (Test-Path $tempDir)) {
    New-Item -ItemType Directory -Path $tempDir | Out-Null
}

Get-ChildItem -Path $folderPath -Filter *.msg | ForEach-Object {
    $msgFullName = $_.FullName
    $docFullName = $msgFullName -replace '\.msg$', '.doc'
    $pdfFullName = $msgFullName -replace '\.msg$', '.pdf'

    # 加载MSG并保存为DOC
    $msg = $outlook.CreateItemFromTemplate($msgFullName)
    $msg.SaveAs($docFullName, 4) # 4对应olDoc格式

    # 打开DOC文档
    $doc = $word.Documents.Open($docFullName)
    $selection = $word.Selection

    # 遍历邮件附件,嵌入到文档末尾
    if ($msg.Attachments.Count -gt 0) {
        # 移动到文档末尾并添加分隔线
        $selection.EndKey([ref] 6) # 6对应wdStory,即文档末尾
        $selection.TypeText("`n--- 附件 ---`n")

        foreach ($attachment in $msg.Attachments) {
            $tempFilePath = Join-Path $tempDir $attachment.FileName
            $attachment.SaveAsFile($tempFilePath)

            # 优先尝试直接插入文件内容(如文档、图片)
            $selection.EndKey([ref] 6)
            $insertSuccess = $true
            try {
                $selection.InsertFile($tempFilePath, $false, $false, $false, $false)
            } catch {
                $insertSuccess = $false
            }

            # 无法直接插入的文件,以OLE对象形式嵌入并标注文件名
            if (-not $insertSuccess) {
                $selection.EndKey([ref] 6)
                $selection.TypeText("`n附件: $($attachment.FileName)`n")
                $doc.Shapes.AddOLEObject($tempFilePath) | Out-Null
            }

            # 删除临时文件
            Remove-Item $tempFilePath -Force -ErrorAction SilentlyContinue
        }
    }

    # 保存为PDF并关闭文档
    $doc.SaveAs([ref] $pdfFullName, [ref] 17) # 17对应wdFormatPDF
    $doc.Close([ref] $false) # 不保存带附件的DOC,若需保留则改为$true

    # 释放MSG对象
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($msg) | Out-Null
}

# 清理临时目录
Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue

# 释放COM对象,避免内存泄漏
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($word) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($outlook) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

关键说明

  • 临时目录:临时存放附件,插入Word后立即删除,避免残留文件
  • 附件插入逻辑:优先直接插入可识别的文件内容(如文档、图片),无法直接插入的文件以OLE对象形式嵌入,并标注文件名
  • COM对象释放:手动释放Outlook和Word的COM对象,防止内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 17:40:30