Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs
Contact   •   Articles   •   Products   •   Support   •   Search
Ad-free experience sponsored by:
ASPOSE - the market leader of .NET and Java APIs for file formats – natively work with DOCX, XLSX, PPT, PDF, images and more

COM Object Access and dynamic in .NET Core 2.x

On this page:

I've been playing around with some old legacy code that uses an ASP.NET front end to some really old FoxPro COM servers. Yup - very Old Skool! It's part of an old framework that works well on full .NET.

Recently I've been toying with the idea moving this to .NET Core to make the local development experience a lot smoother. With easy Kestrel self-hosting the need to use IIS or local IIS Express goes away and even for this old monolith that would be a huge win.

The old framework is implemented in .NET HttpModule/Handler and moving this to .NET Core wouldn't be a big effort which is even more of an incentive. The upside would be that it still works in IIS especially now in .NET Core 2.2 with the new and improved InProcess .NET Core hosting capability.

COM in .NET Core

COM of course is old tech and totally Windows specific, which is fine in this case. But in my case it's the only way to interop with the old legacy FoxPro COM server/applications.

Surprisingly .NET Core - when running on Windows at least - supports COM access, which means you can instantiate and call COM objects from .NET Core in the same way as full framework. Well almost...

Although .NET Core is cross-platform, COM Interop is a purely Windows specific feature. Incidentally even .NET Standard includes support for the COM related Reflection and Interop functions with the same Windows specific caveat.

Not so Dynamic

The good news is that COM Interop works in .NET Core. The bad news is that COM Interop using the C# dynamic keyword and the Dynamic Language Runtime in .NET does not.

Here's a silly example that's easy to try out using InternetExplorer.Application to automate that crazy Web Browser. Not very useful but an easy to play with COM Server that's generically available on Windows.

The following code uses raw Reflection in .NET Core to access a COM object and this works just fine in both full .NET 4.5+ or .NET Core 2.x:

public void ComAccessReflectionCoreAnd45Test()
    // this works with both .NET 4.5+ and .NET Core 2.0+

    string progId = "InternetExplorer.Application";
    Type type = Type.GetTypeFromProgID(progId);
    object inst = Activator.CreateInstance(type);

    inst.GetType().InvokeMember("Visible", ReflectionUtils.MemberAccess | BindingFlags.SetProperty, null, inst,
        new object[1]

    inst.GetType().InvokeMember("Navigate", ReflectionUtils.MemberAccess | BindingFlags.InvokeMethod, null,
        inst, new object[]

    //result = ReflectionUtils.GetPropertyCom(inst, "cAppStartPath");
    bool result = (bool)inst.GetType().InvokeMember("Visible",
        ReflectionUtils.MemberAccess | BindingFlags.GetProperty, null, inst, null);
    Console.WriteLine(result); // path             

I used this in a multi-targeted project targeting net46 and netcore2.1. The above code works against either target.

Using the much simpler dynamic code however, works only in .NET 4.5 but not in .NET Core 2.x:

public void ComAccessDynamicCoreAnd45Test()
    // this does not work with .NET Core 2.0

    string progId = "InternetExplorer.Application";
    Type type = Type.GetTypeFromProgID(progId);
    dynamic inst = Activator.CreateInstance(type);

    // dynamic inst is set, but all prop/metho access on dynamic fails
    inst.Visible = true;

    bool result = inst.Visible;

This is a bummer, but it looks like this will get fixed in .NET Core 3.0. I was just about to post an issue on the CoreFx Github repo, when I saw this:

and it looks it's been added to be fixed for .NET Core 3.0.

I'm glad to see that COM at least works. In this particlar case, I'm only dealing with a handful of Interop calls so I don't mind too much using my ReflectionUtils in Westwind.Utilties to do it.

But for more complex use cases it sure is a lot easier to use dynamic to automatically handle the type casting and more natural member syntax. Hopefully this will get addressed before 3.0 ships later this year - chances are good seeing that a lot of focus in 3.0 is around making old Windows related frameworks like WinForms and WPF work in .NET Core. COM is just one more step removed back from that 😂.

this post created and published with Markdown Monster
Posted in .NET Core  .NET  COM  


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2019