Friday, August 8, 2014

Two gotchas when developing a COM component using C# and .NET 4

By Steve Endow

(Warning: This post is full-developer geek-out technical.  Unless C#, COM, default constructors, and RegAsm are in your vocabulary, you may want to save this one for a future case of insomnia.)

In the last year, I've had two customers request Dynamics GP integrations packaged up as COM DLLs so that their internal applications can call the DLL to import transactions into GP.

The benefit of this approach is that their internal application can control exactly when and how data is imported in GP.  They don't have to wait for a scheduled import or some other external process to trigger the import.

The customer's internal application is creating the data, so they want to start the import as soon as the data is ready, call the import, and have their application verify that everything imported successfully.  This process can produce a very tightly integrated and streamlined process.

Not a problem.  For applications that are developed using something other than .NET, many support the older COM software interface standard.  Fortunately, .NET makes it relatively easy to expose .NET assemblies as COM components.  With newer versions of Visual Studio, it is just a single checkbox.

Very simple, right?

I previously developed a COM-Visible .NET DLL for a customer and that's all it took.  But one difference for that project is that the customer asked that I use Visual Basic.  With the Visual Basic DLL, the DLL registered fine and I had zero COM issues, somewhat to my surprise.

But this time, when my customer tried to register the C# DLL as a COM component, they received this error.

RegAsm : error RA0000 : Failed to load 'C:\path\import.dll' because it is not a valid .NET assembly

So, what was different?  Why was the regasm command failing?

Well, after some puzzling, I realized that two things were different this time.  First, I realized that I developed this DLL using .NET 4.0, whereas the last one was .NET 3.5.  While that may not seem like a big deal, I now know that it makes all the difference.  It turns out that with .NET 4, there is a different version of RegAsm.

So instead of this path for RegAsm.exe


You need to use this path with .NET 4:


NOTE:  If your library is compiled for x64, you need to use the Framework64 directory:


Okay, so now that I had figured that out, and used the .NET 4 version of RegAsm, I received a different error.

RegAsm : warning RA0000 : No types were registered

Huh.  I tried a few different options for RegAsm, but just couldn't get it to recognize the COM interface.

After some moderately deep Googling, I found a helpful post on Stack Overflow.  The solution poster noted that with C#, you need to have a default constructor for COM.  Um, okay, so...wait a minute, what?  Huh?

And that's when I remembered.  My prior COM project used VB, whereas this one was C#.  Well, one of the things I learned during my transition from VB to C# was that VB essentially hides constructors from you.  And looking at my VB code, it looks like I did a fair amount of digging and added the "Public Sub New()" method, which is required for a COM visible class.

With C#, it is similar, but the syntax is slightly different.

    public class Import

        //Default constructor needed for COM
        public Import()

You just have to add an empty default constructor for the public class in order to make it COM visible.

Obvious, right?  Not so much.

Now that I know, it's no big deal, but when I'm asked to do another COM visible component in a few years, I'm sure I'll forget.  Hence this blog post!

Anyway, after adding the default constructor and recompiling, the DLL registered just fine.

Steve Endow is a Microsoft MVP for Dynamics GP and a Dynamics GP Certified IT Professional in Los Angeles.  He is the owner of Precipio Services, which provides Dynamics GP integrations, customizations, and automation solutions.

You can also find him on Google+ and Twitter

No comments: