Word.Application ComObject errors in PowerShell

2019-05-04 05:02发布

问题:

I'm unable to get a Word 2010 (14.0.x) document to SaveAs or Close using Powershell. From all the tuts online it seems like it should be working with 2.0, but I don't have that anymore.

Simple case:

$Path = "C:\MyDoc.docx"
$Word = New-Object -comobject Word.Application
$Word.Visible = $True #Do this to close it out without task manager
$Doc = $Word.Documents.Open($Path)
$Doc.SaveAs($Path)
$Doc.Close()

At this point everything works up until the saving and closing:

Argument: '1' should be a System.Management.Automation.PSReference. Use [ref].
At line:5 char:1
+ $Doc.SaveAs($Path)
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : NonRefArgumentToRefParameterMsg

Argument types do not match
At line:6 char:1
+ $Doc.Close()
+ ~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], ArgumentException
    + FullyQualifiedErrorId : Argument types do not match

It seems like any methods that Get-Member shows as having arguments fail. For instance, calling a simple $Doc.Save() works fine, it seems. Looking at the MSDN info on those methods it looks like it takes things like the SaveChanges method, but that's honestly beyond my skills at this point.

I've tried passing $Null or $True or $False in hopes of getting lucky, but it just keeps balking at me.

All I've been able to find is that it is apparently linked to PS 3.0 Beta (seems to work fine in 2.0 for people) and a comment Ed Wilson hasn't gotten back to.

回答1:

I was also struggling al lot with this error, but got finally around it by calling the "Value" property of the PSReference (I got my Information here: https://msdn.microsoft.com/en-us/library/system.management.automation.psreference(v=vs.85).aspx )

this finally resulted in the codeLines:

$filename = [ref]"C:\Temp\pv_report.docx"    
[ref]$option = [Microsoft.Office.Interop.Word.WdSaveFormat] -as [type]
$document.SaveAs(([ref]$filename).Value, ([ref]$option::wdFormatDocumentDefault).Value)
$document.Close()


回答2:

You just need to use [ref] when you call SaveAs. This worked for me:

$Path = "C:\MyDoc.docx"
$NewPath = "C:\MyDocRenamed.docx"
$Word = New-Object -comobject Word.Application
$Word.Visible = $True #Do this to close it out without task manager
$Doc = $Word.Documents.Open($Path)
$Doc.SaveAs([ref] $NewPath)
$Doc.Close()


回答3:

This might help you:

http://msdn.microsoft.com/en-us/library/office/cc626294(v=office.12).aspx#VSTO3PowerTools_OfficeInteropAPIExtensions

Office Interop API Extensions

The Office Interop API Extensions tool uses new features found in Microsoft .NET Framework 3.5 and Microsoft Visual C# 3.0 to wrap the Office object model and provide a more productive environment for the C# developer. Specifically, it employs extension methods, object initializers, and nullable types to create a simplified, strongly-typed, and, in some cases, Microsoft Visual Basic–like API. It is not a complete managed API for Office, but is designed to augment the raw object model in useful ways.

The Office object model was originally targeted at dynamic languages such as Microsoft Visual Basic for Applications (VBA) and Visual Basic. As such, it makes extensive use of some of their capabilities, such as late-binding and optional parameters. Being an early-bound and strongly-typed language, C# can be awkward, tedious, and error prone when used in this context. The Office Interop API Extensions, with its simplified and strongly-typed API, enables C# developers to be as productive in this context as Visual Basic developers.

I know PowerShell 3.0 is based off of CLR4, but this assembly should still load ok. It removes the need for all of the [ref] parameters. Since a lot of this API is based on extension methods (something that doesn't exist in powershell) you'll have to pass the $word or $doc instance as the first parameter for a lot of the methods.