1

Q: Can I make a native client that consumes a .NET COM component, using reg free COM?

I.e. Can I make a C++ application with COM info in its manifest, instead of registering the component (COM 'stuff') in the registry?


Note: I started looking at reg free COM with this question in mind, and didn't find a quick answer via web search. When I found the answer, thought'd I'd post on SO in case helps anyone else searching...

Daryn
  • 4,791
  • 4
  • 39
  • 52

2 Answers2

2

Yes.

And here's an MSDN has an article (from 2005) that walks through a working example of:

...the registration-free activation of a .NET Framework-based component by native clients via COM interop. (11 printed pages)
https://msdn.microsoft.com/en-us/library/ms973915.aspx (accessed Jan 2015)

Daryn
  • 4,791
  • 4
  • 39
  • 52
  • On the one hand, this is a pretty useful blog post. On the other, when that link breaks this answer is gonna be annoyingly useless. Could you at least summarize it here before linking to the full walk-through? – Shog9 Aug 25 '15 at 16:56
  • Hmm. Good point about when the link dies, but challenging as I noted "11 printed pages" : ) I'll see what I can do – Daryn Aug 26 '15 at 17:04
2

Daryn,

This blog entry explain you how to do it: http://blogs.msdn.com/b/rodneyviana/archive/2015/08/24/pure-native-c-consuming-net-classes-without-com-registration.aspx

Basically you use a entry point to return the pointer to the interface (using DllExport Nuget for "export"):

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using RGiesecke.DllExport;

namespace ContosoCom
{

 public static class Exports
 {
     [DllExport(CallingConvention = CallingConvention.Cdecl)]
     public static void GetClass([Out] [MarshalAs((UnmanagedType.Interface))] out IMyClass pInterface)
     {
         pInterface = new MyClass();
     }
 }


 [ComVisible(true)]
 [System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)]
 public interface IMyClass
 {
     void DisplayMessageBox([MarshalAs(UnmanagedType.BStr)] string Text);
     void GetTicksAndDate([Out] out MyStruct Structure);
 }

 [ComVisible(true)]
 [StructLayout(LayoutKind.Sequential, Pack = 8)]
 public struct MyStruct
 {
     public long TicksOfNow;
     public int Day;
     public int Month;
     public int Year;
 }

 [ComVisible(true)]
 [ClassInterface(ClassInterfaceType.None)]
 [ComDefaultInterface(typeof(IMyClass))]
 public class MyClass : IMyClass
 {

     public void DisplayMessageBox(string Text)
     {
         MessageBox.Show(Text);
     }

     public void GetTicksAndDate(out MyStruct Structure)
     {
         Structure.TicksOfNow = DateTime.Now.Ticks;
         Structure.Day = DateTime.Now.Day;
         Structure.Month = DateTime.Now.Month;
         Structure.Year = DateTime.Now.Year;
     }
 }

}

And this is how the C++ code looks like:

#include "stdafx.h"
#import "..\..\bin\Debug\ContosoCom.tlb" auto_rename


using namespace ContosoCom;
typedef void(*pGetClass)(IMyClass **iMyClass);


int _tmain(int argc, _TCHAR* argv[])
{
 pGetClass getClass = NULL;
 IMyClass *mc = NULL;

 HINSTANCE hDLL = 0;
 // load the DLL

 hDLL = ::LoadLibrary(L"ContosoCom.dll");

 ::CoInitialize(NULL);

 if(!hDLL)
 {
     printf("ERROR: Unable to load library ContosoCom.dll\n");
     return -1;
 }


 //
 // TO DO: Add code here to get an instance of MyClass
 //
 getClass = (pGetClass)GetProcAddress(hDLL, "GetClass");

 if(!getClass)
 {
     printf("ERROR: Unable to find entry for GetClass()\n");
     return -1;

 }

 getClass(&mc);

 // At this point we do not have how to get a pointer even with the libray loaded

 // End of TO DO

 if(!mc)
 {
     printf("ERROR: Unable to get a pointer for MyClass\n");
     return -1;
 }

 mc->DisplayMessageBox("Hello World from native to .NET without registration");
 MyStruct st;
 ZeroMemory(&st, sizeof(MyStruct));
 mc->GetTicksAndDate(&st);
 printf("Ticks %I64i\n",st.TicksOfNow);
 printf("Today is %i/%i/%i\n",st.Month,st.Day,st.Year);


 printf("SUCCESS: Leaving gracefully\n");
 return 0;
}
Rodney Viana
  • 466
  • 2
  • 5