当传递VBA类的实时实例时,C#ITypeInfo.GetContainingTypeLib失败 [英] C# ITypeInfo.GetContainingTypeLib fails when passed live instance of VBA Class
问题描述
因此,我尝试了在VBA类实例上调用 ITypeInfo
的尝试,尽管看起来很有希望,但我想看看是否可以引用其包含的项目(一个类似物)到类型库。我以为 ITypeInfo.GetContainingTypeLib
可能有用,但是它抛出一个异常,指示VBA无法合作。任何人都对VBA可能与标准COM规范的处理方式有所不同?
So I have experimented on calling ITypeInfo
on a VBA Class instance and whilst it looks promising I wanted to see if I could get a reference to its containing project, an analogue to a type library. I thought ITypeInfo.GetContainingTypeLib
might be useful but it throws an exception indicating VBA won't co-operate. Anyone got any ideas about how VBA maybe doing things differently from the standard COM specification?
C#类库代码在这里。注册COM互操作,并在 AssemblyInfo.cs 中设置 COMVisible(true)
以使其可从VBA访问。
The C# Class library code is here. Register for COM interop and set COMVisible(true)
in AssemblyInfo.cs to make it accessible from VBA. VBA client code given below.
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
namespace TypeLibraryInspector
{
[ComImport()]
[Guid("00020400-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDispatch
{
[PreserveSig]
int GetTypeInfoCount(out int Count);
[PreserveSig]
int GetTypeInfo
(
[MarshalAs(UnmanagedType.U4)] int iTInfo,
[MarshalAs(UnmanagedType.U4)] int lcid,
out System.Runtime.InteropServices.ComTypes.ITypeInfo typeInfo
);
//void GetTypeInfo(int typeInfoIndex, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler,
// MarshalTypeRef = typeof(System.Runtime.InteropServices.CustomMarshalers.TypeToTypeInfoMarshaler))] out Type typeInfo);
//void GetTypeInfo(int typeInfoIndex, int lcid, out IntPtr piTypeInfo);
[PreserveSig]
int GetIDsOfNames
(
ref Guid riid,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)]
string[] rgsNames,
int cNames,
int lcid,
[MarshalAs(UnmanagedType.LPArray)] int[] rgDispId
);
[PreserveSig]
int Invoke
(
int dispIdMember,
ref Guid riid,
uint lcid,
ushort wFlags,
ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
out object pVarResult,
ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo,
IntPtr[] pArgErr
);
}
public interface IInspector
{
void InspectThisObject(object vbaClassInstance);
}
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IInspector))]
public class Inspector : IInspector
{
private const int S_OK = 0; //From WinError.h
private const int LOCALE_SYSTEM_DEFAULT = 2 << 10; //From WinNT.h == 2048 == 0x800
void IInspector.InspectThisObject(object vbaClassInstance)
{
//https://limbioliong.wordpress.com/2011/10/18/obtain-type-information-of-idispatch-based-com-objects-from-managed-code/
IDispatch pDispatch = (IDispatch)vbaClassInstance;
ITypeInfo piTypeInfo;
pDispatch.GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, out piTypeInfo);
string s1; string s2; string s3;
int i1;
piTypeInfo.GetDocumentation(-1, out s1, out s2, out i1, out s3);
//s1 = "Class1" good
//s2 = null shame
ITypeLib piTypeLib;
int pIndex;
piTypeInfo.GetContainingTypeLib(out piTypeLib, out pIndex); // <-- throws Exception 0x800A88C1
}
}
}
所以有些客户VBA在这里
So some client VBA is here
Sub Test()
Dim oInspector As TypeLibraryInspector.Inspector
Set oInspector = New TypeLibraryInspector.Inspector
Dim oClass1 As Class1
Set oClass1 = New Class1
oInspector.InspectThisObject oClass1
End Sub
其中Class1可以是任何类,但我有两个空函数
where Class1 can be any class, I have two empty functions in mine but I do not think that relevant.
我问过等效的C ++问题。
推荐答案
如果dll暴露于com中,则必须在regsvr32中注册
if the dll is com exposed it has to be registered with regsvr32
另外,您可能需要GAC .net程序集
Also u might need to GAC the .net assembly
这篇关于当传递VBA类的实时实例时,C#ITypeInfo.GetContainingTypeLib失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!