我正在尝试在.NET中引发一个事件,并通过VBA应用程序通过COM获取它。 This answer非常有助于让我的事件在类型库中正确显示。
在VBA方面,一切看起来都是合法的。我有一个对象变量声明" WithEvents" ,IDE允许我添加事件处理程序,编译器不会抱怨。但是在运行时,当我使用New来创建对象时,我得到Run-time error 459: This component doesn't support this set of events.根据帮助文件,这意味着:"你试图使用WithEvents变量和一个可以'作为指定事件集的事件源。"
我真的不知道为什么。我不认为我违反了帮助文件也解释的Implements规则。下面是类型库的IDL(幸运的是它很短)。任何人都可以看到导致此类型库的错误吗?
编辑:--------------------------------
记住我之前有几个版本的这个组件的COM版本,我比较了它的IDL,并注意到它上面的两个接口都标记为nonextensible。这与WithEvents失败有关吗?当我使用该组件而不是新组件时,它不会在" New"并正确接收事件。
我看到的唯一其他差异是hidden属性和事件界面的双下划线命名(以及为什么这两者之间的关系?)
来自.NET的.tlb
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: Drawing Locator.tlb
[
uuid(4ABD3AAB-CA6A-48D6-8E4E-8082645A0F05),
version(1.0),
custom(90883F05-3D28-11D2-8F17-00A0C9A6186D, "Drawing Locator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e02c23b3671cff4d")
]
library Drawing_Locator
{
// TLib : // TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}
importlib("mscorlib.tlb");
// TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface IDrawingFinder;
dispinterface IDrawingFinderEvents;
typedef [uuid(565D6F5A-13BF-4794-AC35-3ECC4329B280), version(1.0) ,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Drawing_Locator.FileTypes")
]
enum {
FileTypes_Tiff = 0,
FileTypes_Acad = 1
} FileTypes;
[
uuid(78B2A29B-C289-4D65-B373-C345AD06BD31),
version(1.0),
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Drawing_Locator.DrawingFinder")
]
coclass DrawingFinder {
interface _Object;
[default] interface IDrawingFinder;
[default, source] dispinterface IDrawingFinderEvents;
};
[
odl,
uuid(21DBD6E1-D04F-4335-B189-5B49EB960605),
version(1.0),
dual,
oleautomation,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Drawing_Locator.IDrawingFinder")
]
interface IDrawingFinder : IDispatch {
[id(0x60020000)]
HRESULT GetFiles(
[in] BSTR PartNumber,
[in] FileTypes FileType,
[in] VARIANT_BOOL OpenFiles,
[out, retval] SAFEARRAY(BSTR)* pRetVal);
[id(0x60020001)]
HRESULT RegisterTiffToImaging();
};
[
uuid(60314738-04D1-4B4A-BC39-6A81DE24A13B),
version(1.0),
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Drawing_Locator.IDrawingFinderEvents")
]
dispinterface IDrawingFinderEvents {
properties:
methods:
[id(0x00000001)]
void PartNumberChanged([in] BSTR NewPartNumber);
[id(0x00000002)]
void Searching([in, out] VARIANT_BOOL* CancelSearch);
};
};
.NET端的代码:
Imports System.Runtime.InteropServices
<ComVisible(True)>
<InterfaceType(ComInterfaceType.InterfaceIsDual)>
<Guid("21DBD6E1-D04F-4335-B189-5B49EB960605")>
Public Interface IDrawingFinder
Function GetFiles(ByVal PartNumber As String, ByVal FileType As FileTypes, ByVal OpenFiles As Boolean) As <MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VarEnum.VT_BSTR)> String()
Sub RegisterTiffToImaging()
End Interface
<ComVisible(True)>
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)>
<Guid("60314738-04D1-4B4A-BC39-6A81DE24A13B")>
Public Interface IDrawingFinderEvents
<System.Runtime.InteropServices.DispId(1)>
Sub PartNumberChanged(ByVal NewPartNumber As String)
<System.Runtime.InteropServices.DispId(2)>
Sub Searching(ByRef CancelSearch As Boolean)
End Interface
<ComVisible(True)>
<GuidAttribute("565D6F5A-13BF-4794-AC35-3ECC4329B280")>
Public Enum FileTypes
Tiff
Acad
End Enum
<System.Runtime.InteropServices.ComVisible(False)>
Public Delegate Sub OnPartNumberChanged(ByVal NewPartNumber As String)
<System.Runtime.InteropServices.ComVisible(False)>
Public Delegate Sub OnSearching(ByRef CancelSearch As Boolean)
<ComVisible(True)>
<ClassInterface(ClassInterfaceType.None)>
<ComDefaultInterface(GetType(Drawing_Locator.IDrawingFinder))>
<ComSourceInterfaces(GetType(Drawing_Locator.IDrawingFinderEvents))>
<GuidAttribute("78B2A29B-C289-4D65-B373-C345AD06BD31")>
Public Class DrawingFinder
Implements IDrawingFinder
Public Event PartNumberChanged As OnPartNumberChanged
Public Event Searching As OnSearching
'Event PartNumberChanged(ByVal NewPartNumber As String)
'Event Searching(ByRef CancelSearch As Boolean)
Private Declare Sub SHAddToRecentDocs Lib "shell32.dll" (ByVal uFlags As Integer, ByVal pv As String)
Private Const SHARD_PATH As Integer = 2
Dim worker As BackgroundWorker
Dim eventargs As DoWorkEventArgs
Public Function GetFiles(ByVal PartNumber As String, ByVal FileType As FileTypes, ByVal OpenFiles As Boolean) As String() Implements IDrawingFinder.GetFiles
End Sub
End Class
来自VB6的旧(工作).tlb
// typelib filename: DrawingFinder.dll
[
uuid(D11F3F87-F149-4060-81D3-F46A90DA28CB),
version(1.0),
helpstring("Finds and Opens Engineering Drawings"),
custom(50867B00-BB69-11D0-A8FF-00A0C9110059, 9782)
]
library DrawingSearch
{
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface _DrawingFinder;
dispinterface __DrawingFinder;
[
odl,
uuid(A0AB1327-59A7-45E0-8992-92DB8253368B),
version(1.0),
hidden,
dual,
nonextensible,
oleautomation
]
interface _DrawingFinder : IDispatch {
[id(0x60030000)]
HRESULT OpenAcadDwgs([in] BSTR PN);
[id(0x60030001)]
HRESULT OpenImageFiles([in] BSTR PN);
[id(0x60030002)]
HRESULT GetAcadDwgs(
[in] BSTR PN,
[out, retval] SAFEARRAY(BSTR)* );
[id(0x60030003)]
HRESULT GetImageFiles(
[in] BSTR PN,
[out, retval] SAFEARRAY(BSTR)* );
};
[
uuid(95E5F4E3-6A45-4B60-845B-3A78E75A8319),
version(1.0)
]
coclass DrawingFinder {
[default] interface _DrawingFinder;
[default, source] dispinterface __DrawingFinder;
};
[
uuid(BB78905B-297B-4D7C-80B0-3297D4B07AFE),
version(1.0),
hidden,
nonextensible
]
dispinterface __DrawingFinder {
properties:
methods:
[id(0x00000001)]
void Searching([in, out] VARIANT_BOOL* Cancel);
[id(0x00000002)]
void PartNumberChanged([in] BSTR FormattedPN);
};
typedef [uuid(4F3E20EC-EE21-40E8-813F-9292605EF941), version(1.0)]
enum {
errArgument_OutOfRange = 0x80040001,
errDrawing_FolderNotFound = 0x80040002,
errDrawing_FileNotFound = 0x80040003,
errDrawing_BadShortcut = 0x80040004,
errDrawing_ViewerNotFound = 0x80040005,
errDrawing_Open = 0x80040006,
errDrawing_SearchCancelled = 0x80040007,
errAcad_NotAvailable = 0x80040008
} ErrorTypeEnum;
};
答案 0 :(得分:1)
我编译.net版本,然后使用OLEVIEW从.net和COM VB6版本生成TLB的代码。
然后将它们比作BeyondCompare或Araxis。
获取所有排队的GUID,然后查找其他任何差异。
没有什么东西从我发布的内容中跳出来,但我花了很多时间来比较TLB,以便让.net版本“恰到好处”。
我不确定关于发布链接的SO的礼节,但是我前段时间做了一个项目,它在VB6中启用了Bookmark和断点保存。这是一个VB.net项目,它为VB6 IDE生成了一个COM插件,所以那里有很多COM互操作示例代码。
在这里查看: