使用Powershell和Word SaveAs()的麻烦

时间:2016-04-07 21:24:36

标签: .net powershell ms-word office-interop

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

首先,当我给出$ word.Visible = $ False时,会出现Word窗口。

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

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

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()

2 个答案:

答案 0 :(得分:1)

为什么要求打开只读

您正在使用Microsoft Word COM对象

如果没有正确关闭它们,COM对象会因引发问题而臭名昭着。在您调用$word.quit的脚本中,在大多数情况下不会关闭word.exe进程。

您收到文档处于打开状态的错误,因为之前脚本运行的进程尚未关闭。您可能在脚本到达$word.quit()之前点击了停止,可能还没有退出。

保存您的所有工作并尝试Get-Process WINWORD | stop-Process -force这会终止您计算机上的所有打开文字进程。我打赌你会在那之后工作。 但是你还没有解决脚本留下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

的答案

答案 1 :(得分:0)

尼克的回答被标记为答案。这是在这种情况下工作的结果脚本。 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
相关问题