ITypeLib2.GetLibStatistics() always throws AccessViolationException in C#
See the question and my original answer on StackOverflowITypeLib2
defined by .NET is "simply" wrong. It's defined like this in C/C++:
ITypeLib2 : public ITypeLib
{
public:
virtual HRESULT STDMETHODCALLTYPE GetCustData(REFGUID guid, VARIANT *pVarVal) = 0;
virtual HRESULT STDMETHODCALLTYPE GetLibStatistics(ULONG *pcUniqueNames, ULONG *pcchUniqueNames) = 0;
virtual HRESULT STDMETHODCALLTYPE GetDocumentation2(INT index, LCID lcid, BSTR *pbstrHelpString, DWORD *pdwHelpStringContext, BSTR *pbstrHelpStringDll) = 0;
virtual HRESULT STDMETHODCALLTYPE GetAllCustData(CUSTDATA *pCustData) = 0;
}
And like this in .NET
public interface ITypeLib2 : ITypeLib
{
... ITypeLib ...
void GetCustData(ref Guid guid, out object pVarVal);
void GetDocumentation2(int index, out string pbstrHelpString, out int pdwHelpStringContext, out string pbstrHelpStringDll);
void GetLibStatistics(IntPtr pcUniqueNames, out int pcchUniqueNames);
void GetAllCustData(IntPtr pCustData);
}
So GetDocumentation2
and GetLibStatistics
have been switched and you're calling GetDocumentation2
instead with obviously wrong parameters (😱).
This can be checked in a debugger:
So you must redefine ITypeLib2
in your code like this:
[ComImport, Guid("00020411-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITypeLib2 : ITypeLib
{
[PreserveSig]
new int GetTypeInfoCount();
new void GetTypeInfo(int index, out ITypeInfo ppTI);
new void GetTypeInfoType(int index, out System.Runtime.InteropServices.ComTypes.TYPEKIND pTKind);
new void GetTypeInfoOfGuid(ref Guid guid, out ITypeInfo ppTInfo);
new void GetLibAttr(out IntPtr ppTLibAttr);
new void GetTypeComp(out ITypeComp ppTComp);
new void GetDocumentation(int index, out string strName, out string strDocString, out int dwHelpContext, out string strHelpFile);
new bool IsName([MarshalAs(UnmanagedType.LPWStr)] string szNameBuf, int lHashVal);
new void FindName([MarshalAs(UnmanagedType.LPWStr)] string szNameBuf, int lHashVal, [Out][MarshalAs(UnmanagedType.LPArray)] ITypeInfo[] ppTInfo, [Out][MarshalAs(UnmanagedType.LPArray)] int[] rgMemId, ref short pcFound);
[PreserveSig]
new void ReleaseTLibAttr(IntPtr pTLibAttr);
void GetCustData(ref Guid guid, out object pVarVal);
void GetLibStatistics(IntPtr pcUniqueNames, out int pcchUniqueNames);
void GetDocumentation2(int index, out string pbstrHelpString, out int pdwHelpStringContext, out string pbstrHelpStringDll);
void GetAllCustData(IntPtr pCustData);
}
And it will work.
I've created an issue for this https://github.com/dotnet/runtime/issues/99946