Accessing a custom service in C++ from a C# add-in

I have a VsPackage developed in unmanaged C++ (ViEmu), which has some compatibility issues with DevExpress' CodeRush (.NET). I have a solution to these issues which involves proffering a service from ViEmu and notifying it from a CodeRush plug-in. I have almost everything ready but the actual call to the service itself. I think my problems are due to my lack of experience with C# code.

This is the way the service is declared in C++:

MIDL_INTERFACE("AF8F75A1-A458-4F1F-BFAE-3B1B0E27D97A")
IViEmuService : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE EnterInsertMode( ) = 0;
};

This is how I declare this interface on the C# end:

[Guid("AF8F75A1-A458-4F1F-BFAE-3B1B0E27D97A"), InterfaceType(ComInterfaceType.InterfaceIsDual)]
interface IViEmu
{
void EnterInsertMode();
}

This is how I try to obtain and call the service:

using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;


IOleServiceProvider isp = CodeRush.ApplicationObject as IOleServiceProvider;

IntPtr ppObj;
System.Guid guid_service = new System.Guid("D61C5542-1D52-4731-A789-9A9E5798F052");
System.Guid guid_iviemu = new System.Guid("AF8F75A1-A458-4F1F-BFAE-3B1B0E27D97A");

if (isp.QueryService(
ref guid_service,
ref guid_iviemu,
out ppObj
) == DevExpress.CodeRush.Win32.HRESULT.S_OK)
{
IViEmu viemu = Marshal.GetObjectForIUnknown(ppObj) as IViEmu;
if (viemu != null)
viemu.EnterInsertMode();
}

I think the object I get back from QueryService() is right, as it doesn't work fine when ViEmu is not installed. But the call to EnterInsertMode() nukes. I've tried stepping through the assembly code, but I get lost with the layers.

On the other hand, I don't know how to set up a debugging session being able to trace both sides of the communication.

I'll be grateful for any help, or pointer to a resource.

Best regards,

J
----------------------------------------------------
ViEmu - vi/vim emulation for Visual Studio



Answer this question

Accessing a custom service in C++ from a C# add-in

  • jdersch_MSFT

    I don't know if this is the only issue, as I don't work with managed code, but specifying:

    InterfaceType(ComInterfaceType.InterfaceIsDual)]

    would indicate to me that the interface was declared in MIDL with the dual attribute, which requires that it be derived from IDispatch and be automation compatible. Since your interface is derived from IUknown, I would guess that specifying InterfaceIsIUnknown would be more appropriate; however, then you may run into a marshalling issue if you haven't generated an interop assembly from the typelib using tlpexp.exe (I believe that's the name of the tool) or the functionality in VS that does the same thing when specifying a reference to a registered COM component via the reference wizard in C#. The simpler solution might be to re-declare you interface in MIDL so that it derived from IDispatch and has dual specified as n attribute.

    Josh


  • heff89

    Josh,

    You nailed it. Changing InterfaceIsDual to InterfaceIsIUnknown did it completely, no need to use MIDL or an export type library. Cool!

    It was definitely my absolute lack of C# experience, I had just copy'n'pasted the declaration syntax without any real understanding.

    Thanks a bunch!

  • Accessing a custom service in C++ from a C# add-in