Question

When creating COM interface declarations in C# are there any "rules" you have to stick to? I think there are and would like to get some info on it. For example I'm toying around with the ITaskbarList, ITaskbarList2 and ITaskbarList3 interfaces and it seems to me that I

  • Have to declare the order of the members in the manages implementation exactly in the order that they appear in the unmanaged interface declaration.

For example the following appears to work just fine

[ComImport]
[Guid("56FDF342-FD6D-11D0-958A-006097C9A090")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList
{
    void HrInit();
    void AddTab([In] IntPtr hwnd);
    void DeleteTab([In] IntPtr hwnd);
    void ActivateTab([In] IntPtr hwnd);
    void SetActiveAlt([In] IntPtr hwnd);
}

While reordering the members breaks the functionality

[ComImport]
[Guid("56FDF342-FD6D-11D0-958A-006097C9A090")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList
{
    void DeleteTab([In] IntPtr hwnd);
    void HrInit();
    void AddTab([In] IntPtr hwnd);
    void SetActiveAlt([In] IntPtr hwnd);
    void ActivateTab([In] IntPtr hwnd);
}
  • Have to declare inherited unmanaged interfaces in a single managed interface declaration instead of using inheritance on the managed interfaces. I want to declare each of the unmanaged interfaces in their own managed interface (complete with Guid attributes etc) and use inheritance inbetween then, instead of redeclaring the parent declarations in each new interface.

For example, this doesn't appear to work

[ComImport]
[Guid("56FDF342-FD6D-11D0-958A-006097C9A090")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList
{
    void HrInit();
    void AddTab([In] IntPtr hwnd);
    void DeleteTab([In] IntPtr hwnd);
    void ActivateTab([In] IntPtr hwnd);
    void SetActiveAlt([In] IntPtr hwnd);
}

[ComImport]
[Guid("602D4995-B13A-429B-A66E-1935E44F4317")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList2
    : ITaskbarList
{
    void MarkFullscreenWindow(
        [In] IntPtr hwnd,
        [In, MarshalAs(UnmanagedType.Bool)] bool fullscreen);
}

Instead I'm forced to do the following

[ComImport]
[Guid("602D4995-B13A-429B-A66E-1935E44F4317")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITaskbarList2
{
    void HrInit();
    void AddTab([In] IntPtr hwnd);
    void DeleteTab([In] IntPtr hwnd);
    void ActivateTab([In] IntPtr hwnd);
    void SetActiveAlt([In] IntPtr hwnd);
    void MarkFullscreenWindow(
        [In] IntPtr hwnd,
        [In, MarshalAs(UnmanagedType.Bool)] bool fullscreen);
}

I.e declare it in a single interface while still taking the member order into consideration.

So what are the guidelines for declaring managed interfaces for their unmanaged counterparts? Is there anyway to achieve what I want, it interface inheritance on the managed side + declare the members in any order I want (I really just want to sort them alphabetically)

Was it helpful?

Solution

Your discoveries are caused by the same thing: vtables. You can't change the vtable order, and interfaces that inherit from other interfaces always have all the base entries in the vtable as well. So, the rules you're looking for is "make sure the vtable is the same."

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top