Search code examples
c#comsignature

ISearchManager2 issue with signature C#


I'm trying to load ISearchManager2 interface on C#.

Until this moment, everything works fine with ISearchManager. I used the Microsoft.Search.Interop assembly to do that. I can set Catalogs, get some results from indexer and other things.

BUT, now, I want the interface called ISearchManager2, So, I created:

[ComConversionLoss]
[ComImport]
[Guid("DBAB3F73-DB19-4A79-BFC0-A61A93886DDF")]
[InterfaceType(1)]
public interface ISearchManager2 : ISearchManager
{
    void CreateCatalog([MarshalAs(UnmanagedType.LPWStr)] [In] string pszCatalog, out ISearchCatalogManager _out);
    void DeleteCatalog([MarshalAs(UnmanagedType.LPWStr)] string pszCatalog);
}

Same signature and order from searchapi.h which is:

MIDL_INTERFACE("DBAB3F73-DB19-4A79-BFC0-A61A93886DDF")
ISearchManager2 : public ISearchManager
{
public:
    virtual HRESULT STDMETHODCALLTYPE CreateCatalog( 
        /* [string][in] */ __RPC__in_string LPCWSTR pszCatalog,
        /* [out] */ __RPC__deref_out_opt ISearchCatalogManager **ppCatalogManager) = 0;

    virtual HRESULT STDMETHODCALLTYPE DeleteCatalog( 
        /* [string][in] */ __RPC__in_string LPCWSTR pszCatalog) = 0;
};

With a valid ISearchManager Im casting like:

ISearchCatalogManager _out;
Teste _test = (Teste)_searchManager;
_test.CreateCatalog(catalog, out _out);

No error with QueryInterface (that means the interface was found) and no exceptions (with hresults). BUT, the out it's never assigned. Debugging that, I can see the string catalog changing.

[1]

This is before call CreateCatalog. And after:

[2]

I'm presuming the C# it's calling with an extra argument and the second (the out value) it's the string. I tried with PreserveSigAttribute and other things like:

[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void CreateCatalog([MarshalAs(UnmanagedType.LPWStr)] [In] string pszCatalog, out ISearchCatalogManager _out);

Because when I decompile the interface from ISearchManager (from Microsoft.Search.Interop) I can see that attribute on function GetCatalog which have the same signature.

Someone have a ideia why this is happening?


Solution

  • When declaring inherited COM interfaces in .NET you must declare all inherited interfaces members, recursively. So for example, if you have this as the base interface:

    [Guid("2cd90691-12e2-11dc-9fed-001143a055f9"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IBase
    {
        int Blabla();
    }
    

    Then an IDerived definition would be something like this:

    [Guid("65019f75-8da2-497c-b32c-dfa34e48ede6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IDerived
    {
        // IBase methods
        int Blabla();
    
        // IDerived methods
        ...
    }
    

    Or better, like this, if you want to keep inheritance hierarchy in .NET:

    [Guid("65019f75-8da2-497c-b32c-dfa34e48ede6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IDerived : IBase
    {
        // IBase methods
        new int Blabla();
    
        // IDerived methods
        ...
    }