如何用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
相关产品推荐
相关产品推荐

