Home > Uncategorized > Interop trouble in Powershell

Interop trouble in Powershell

I was trying out the Visio 2010 automation SDK, using Powershell, the other day when I stumbled upon an unexpected problem. My code looked something like below. 

Add-Type -AssemblyName ‘Microsoft.Office.Interop.Visio, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c’
$app = new-object Microsoft.Office.Interop.Visio.ApplicationClass
$doc = $app.Documents.Open("C:\temp\test.vsd")
$page = $doc.Pages | select -first 1
$page.Shapes | select ID, Name, NameID, NameU, Text | Out-Host
$shape = $page.Shapes | select -first 1

The code starts off by loading the Visio interop assembly and then creates an application, loads a document, extracts the first page and the first shape on that page. So far, all was fine. However, then I wanted to call GluedShapes using:

$shape.GluedShapes(2, "", $null)

I got a strange error:

Exception calling "GluedShapes" with "3" argument(s): "Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH))"
At line:2 char:19
+ $shape.GluedShapes <<<< (2, "", $null)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ComMethodTargetInvocation

I figured that something was rotten in the state of Powershell interop. A quick and dirty work around was to build a C# wrapper:

Add-Type -ReferencedAssemblies ‘Microsoft.Office.Interop.Visio, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c’ -TypeDefinition @"
using Microsoft.Office.Interop.Visio;
public class ShapeUtils
{
    public static System.Array GluedShapes(object shapeIn, VisGluedShapesFlags flags, string filter)
    {
        Microsoft.Office.Interop.Visio.IVShape x = (Microsoft.Office.Interop.Visio.IVShape)shapeIn;
        return x.GluedShapes(flags, filter, null);
    }
};
"@

and call it using:

[ShapeUtils]::GluedShapes($shape, 2, "")

Alright. That will keep things running. But what happened? The error is complaining about a type mismatch during dispatch. Why on earth is Powershell calling my object using COM dispatch? I started out in the pink ´n fluffy .NET world using the managed interrop assembly that should protect me against everything from the dark ´n scary COM world. Lets check some types:

$app, $doc, $page, $shape | % { $_.GetType() }

This yields:

IsPublic IsSerial Name BaseType
True False ApplicationClass System.__ComObject
True False DocumentClass System.__ComObject
True False __ComObject System.MarshalByRefObject
True False __ComObject System.MarshalByRefObject

$app and $doc looks alright, having proper .NET types but both $page and $shape are pure COM objects and thus will be called using COM dispatch. Having reached this far, I found some interesting links:

    Indeed, the last link confirms that this is a bug that has not been fixed in Powershell 2.0. So, that explains why COM dispatch is activated. The second link also notes that Powershell has trouble calling COM methods having optional arguments. Interestingly, that explains why the call to GluedShapes fails. It is not hard to confirm that this is a bug too; I fired up Visual studio and created an atl project and added a atl com object that implemented the following interface:

interface ITest : IDispatch {

    HRESULT PowershellTest([in]int dummy1, [in, optional]ITest* trouble);

};

 

    and indeed the following lines
    $x = New-Object -ComObject "TestLibrary.Test"
    $x.PowershellTest(0, $null)
    results in our now familiar

Exception calling "PowershellTest" with "2" argument(s): "Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH))"
At line:1 char:13
+ $x.PowershellTest <<<< (0, $null)
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ComMethodTargetInvocation

    I wonder how these things work out in Powershell 3. Well, that is a task for another day.

    Advertisements
    Categories: Uncategorized
    1. No comments yet.
    1. No trackbacks yet.

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s

    %d bloggers like this: