| If you automate Office applications from PowerShell 3.0, you may hit one, at first sight rather weird, yet painful problem. If you need to call the InvokeMember with InvokeMethod type, every PowerShell vs. Office automation example you can find on the internet, may work fine with PowerShell 2.0, while it errors out with the following error:
Object does not match target type
Examples, where you need to call the COM methods low-level with InvokeMember() include the Open method of Excel.Application with US CultureInfo, or yet the Open method of PowerPoint.Application with its WithWindow parameter, or the PowerPoint.Presentation's PrintOut method with PrintToFile parameter.
In PowerShell 2.0, you did it just like this:
# PowerShell 2.0 did well with the following Excel.Application's Open() method
# PowerShell 3.0 and newer returns the "Object does not match target type" error here
$wkBook = $excel.Workbooks.psbase.GetType().InvokeMember('Open', [Reflection.BindingFlags]::InvokeMethod, $null, $excel.Workbooks, $xlsFileFullPath, ([System.Globalization.CultureInfo] 'en-US'))
# or similarly with PowerPoint.Presentation object's PrintOut() method
# again, with PowerShell 3.0 you get the "Object does not match target type" error
[string[]] $paramNames = @('PrintToFile', 'Collate')
[object[]] $paramValues = @($outFile, [Microsoft.Office.Core.MsoTriState]::msoTrue)
[void] $slideDeck.psbase.GetType().InvokeMember(
'PrintOut',
[Reflection.BindingFlags]::InvokeMethod,
$null,
$slideDeck,
$paramValues,
$null, # ParameterModifiers
([System.Globalization.CultureInfo] 'en-US'),
$paramNames
)
What is the reason? The probable reason is PowerShell 3.0 and newer "wraps" the original COM object "too much" in its own wrapper, which you cannot pass into the InvokeMember function.
Solution
Pass down the original BaseObject instead.
# replace the psbase with psobject.BaseObject at both places
$wkBook = $excel.Workbooks.psobject.BaseObject.GetType().InvokeMember('Open', [Reflection.BindingFlags]::InvokeMethod, $null, $excel.Workbooks.psobject.BaseObject, $xlsFileFullPath, ([System.Globalization.CultureInfo] 'en-US'))
# replace the psbase with psobject.BaseObject at both places
[string[]] $paramNames = @('PrintToFile', 'Collate')
[object[]] $paramValues = @($outFile, [Microsoft.Office.Core.MsoTriState]::msoTrue)
[void] $slideDeck.psobject.BaseObject.GetType().InvokeMember(
'PrintOut',
[Reflection.BindingFlags]::InvokeMethod,
$null,
$slideDeck.psobject.BaseObject,
$paramValues,
$null, # ParameterModifiers
([System.Globalization.CultureInfo] 'en-US'),
$paramNames
)
Uff. My 3 hours debugging. I hope this helps you spare some of them. |