使用 Powershell 和 Word SaveAs() 时出现问题

Troubles using Powershell and Word SaveAs()

根据网上的例子,我拼凑了这个脚本,我希望它能将 Word .doc 文件保存为纯文本。它没有。

首先,当我给出 $word.Visible = $False.

时出现单词 window

然后,会出现一个对话框,询问我是否要打开只读副本。没有其他人打开该文档。为什么要问。

最后,错误消息说我的类型不匹配。这是为什么?

PS H:\d2> .\wl.ps1
Processing : H:\d2\checklists\Extract checklist_20120306.doc
Name is now: H:\d2\checklists\Extract checklist_20120306.txt
Exception calling "SaveAs" with "2" argument(s): "Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH))"
At H:\d2\wl.ps1:19 char:5
+     $opendoc.SaveAs([ref]$name.Value,[ref]$saveFormat)
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : COMException

这是脚本的源代码。

$srcfiles = Get-ChildItem -Path . -Recurse -Filter "*.doc*"
$saveFormat = [Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatText
$word = new-object -comobject word.application
$word.Visible = $False

ForEach ($doc in $srcfiles) {
    Write-Host "Processing :" $doc.fullname
    $name = Join-Path -Path $doc.DirectoryName -ChildPath $($doc.BaseName + ".txt")
    Write-Host "Name is now:" $name

    $opendoc = $word.documents.open($doc.FullName)
    $opendoc.SaveAs([ref]$name.Value,[ref]$saveFormat)
    $opendoc.Close()

    $doc = $null
}

$word.quit()

为什么要求以只读方式打开

您正在使用 Microsoft Word COM 对象,

COM 对象因不正确关闭而导致问题而臭名昭著。在大多数情况下,在您的脚本中调用 $word.quit 不会关闭 word.exe 进程。

您收到文档打开的错误消息,因为来自先前脚本 运行 的进程尚未关闭。您可能在脚本到达 $word.quit() 之前单击了停止,或者可能只是没有退出。

保存你所有的工作并尝试Get-Process WINWORD | stop-Process -force这将终止你机器上所有打开的word进程。我敢打赌,在那之后它会起作用。 但是您还没有解决脚本使 doc 一词处于打开状态的问题。尝试将此添加到脚本的末尾:

$word.quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($word)
Remove-Variable word

这是我终止 COM 对象进程的方式,它从未停止过 IE com 对象进程,对于 Word 应该同样有效。

为什么类型不匹配

您需要在 powershell 中加载库:

[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Interop.Word") | Out-Null

您需要更改 .SaveAs 以将文件路径更改为 system.object 而不是 system.string 显然这是 .net 4.0 中所做的更改

$opendoc.SaveAs([ref][system.object]$name,[ref]$saveFormat)

找到类型不匹配错误的答案HERE

尼克的回答被标记为答案。这是在这种情况下工作的结果脚本。 cwd 必须是要转换的所有 .doc 文件的父目录。

[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Interop.Word") | Out-Null
$srcfiles = Get-ChildItem -Path . -Recurse -Filter "*.doc*"
$saveFormat = [Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatText
$word = new-object -comobject word.application
$word.Visible = $False

ForEach ($doc in $srcfiles) {
    Write-Host "Processing :" $doc.fullname
    $name = Join-Path -Path $doc.DirectoryName -ChildPath $($doc.BaseName + ".txt")

    Write-Host "Name is now:" $name

    $word.Visible = $False

    $opendoc = $word.documents.open($doc.FullName)
    $opendoc.SaveAs([ref][system.object]$name, [ref]$saveFormat)
    $opendoc.Close()

    $doc = $null
}

$word.quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($word) | Out-Null
Remove-Variable word