PowerShell 5.1正常运行的PrintOut代码在7.3中失效问题排查与修复
问题原因分析
PowerShell 5.1基于.NET Framework,在COM互操作时会自动处理字符串到object类型的隐式转换,所以直接传字符串类型的$Pages作为[ref]参数能正常工作。而PowerShell 7.3基于.NET Core/.NET 7,对COM互操作的类型检查更严格,不允许直接将字符串类型的引用传递给期望object类型引用的参数,因此抛出类型转换错误。
修改后的代码
这里提供两种可行的修改方案:
方案一:将$Pages转为object类型
通过显式声明$Pages为object类型,适配PowerShell 7.3的类型要求:
$path = 'D:\SchoolWeb\DOCXtoPDF\test.docx' # 目标docx文件路径 $Word = New-Object -ComObject Word.Application $Word.Visible = $false $docx = $Word.Documents.Open($path) $pagesNum = $Word.ActiveDocument.ComputeStatistics([Microsoft.Office.Interop.Word.WdStatistic]::wdStatisticPages) $max = $pagesNum - 2 # 排除最后两页 $Missing = [System.Reflection.Missing]::Value $BackGround = 0 $Append = 0 $Range = 4 # 指定打印自定义页码范围 $OutputFileName = $Missing $From = $Missing $To = $Missing $Item = 0 $Copies = 1 # 显式将$Pages定义为object类型 [object]$Pages = if ($max -gt 1) { "1-$max" } else { "1" } $Word.PrintOut([ref]$BackGround, [ref]$Append, [ref]$Range, [ref]$OutputFileName, [ref]$From, [ref]$To, [ref]$Item, [ref]$Copies, [ref]$Pages) $docx.Close($false) # 清理COM对象,避免Word进程残留 [System.Runtime.Interopservices.Marshal]::ReleaseComObject($docx) | Out-Null [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Word) | Out-Null [GC]::Collect() [GC]::WaitForPendingFinalizers()
方案二:改用From和To参数指定页码范围(更推荐)
直接使用From和To数值参数定义打印范围,避开字符串格式的Pages参数带来的类型问题,更符合Office互操作规范:
$path = 'D:\SchoolWeb\DOCXtoPDF\test.docx' # 目标docx文件路径 $Word = New-Object -ComObject Word.Application $Word.Visible = $false $docx = $Word.Documents.Open($path) $pagesNum = $Word.ActiveDocument.ComputeStatistics([Microsoft.Office.Interop.Word.WdStatistic]::wdStatisticPages) $max = $pagesNum - 2 # 排除最后两页 $Missing = [System.Reflection.Missing]::Value $BackGround = 0 $Append = 0 $Range = 2 # 指定按From和To参数的范围打印 $OutputFileName = $Missing $From = 1 # 起始页码 $To = if ($max -ge 1) { $max } else { 1 } # 结束页码 $Item = 0 $Copies = 1 $Pages = $Missing $Word.PrintOut([ref]$BackGround, [ref]$Append, [ref]$Range, [ref]$OutputFileName, [ref]$From, [ref]$To, [ref]$Item, [ref]$Copies, [ref]$Pages) $docx.Close($false) # 清理COM对象,避免Word进程残留 [System.Runtime.Interopservices.Marshal]::ReleaseComObject($docx) | Out-Null [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Word) | Out-Null [GC]::Collect() [GC]::WaitForPendingFinalizers()
额外说明
- 方案二的逻辑更清晰,类型匹配更可靠,也避免了字符串解析可能出现的格式问题。
- 代码中添加了COM对象的清理逻辑,防止PowerShell执行完毕后Word进程在后台残留。
内容的提问来源于stack exchange,提问作者mwb9aa
相关产品推荐
相关产品推荐

