From examples on the net, I have cobbled together this script which I hope will save Word .doc files as plainText. It does not.
First, the Word window appears when I have given $word.Visible = $False.
Then, a dialog appears asking if I want to open a read-only copy. No one else has the document open. Why is it asking.
Finally, the error message says I have a type mismatch. Why is that?
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
Here is the source code for the script.
$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()
Why is it asking to open read-only
You are using the Microsoft Word COM object,
COM objects are notorious for causing issues if you do not close them properly. In you script calling $word.quit
wont close the word.exe process in most cases.
You are getting the error that the document is open because a process from a previous script run has not been closed. You might have clicked stop before the script got to $word.quit()
of might have just not quit.
Save all your work and try Get-Process WINWORD | stop-Process -force
This will kill all open word processes on your machine. I bet you it will work after that.
But you haven't solved the problem of the script leaving the word doc open. Try adding adding this to the end of your script:
$word.quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($word)
Remove-Variable word
Its how I kill COM object processes and it has never failed to stop a IE com object process, Should work the same for Word.
Why is there a type mismatch
You need to have the library loaded in powershell:
[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Interop.Word") | Out-Null
You need to change your .SaveAs to change the filepath to system.object rather than system.string It was a change made in .net 4.0 apparently
$opendoc.SaveAs([ref][system.object]$name,[ref]$saveFormat)
Found the answer to the type mismatch error HERE
Nick's answer is marked as the answer. This is the resulting script that worked in this situation. The cwd must be the parent directory of all .doc files to convert.
[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
User contributions licensed under CC BY-SA 3.0