WithEvents就错误下沉来自一个.NET组件COM事件 [英] WithEvents error sinking a COM event that comes from a .NET component

查看:248
本文介绍了WithEvents就错误下沉来自一个.NET组件COM事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图提高在.NET中的事件,并把它拾起通过COM由VBA应用程序。 这个答案已经相当有助于让我的活动,以正确地显示在类型库。

在VBA的一面,一切看起来合法的。我有一个对象变量声明为WithEvents就后,IDE让我添加事件处理程序,编译器不抱怨。然而,在运行时,当我使用新创建的对象我得到的运行时错误459:此组件不支持此组事件根据帮助文件,这意味着:你试图使用一个WithEvents就变一个组件,可以科技工作作为事件源事件的指定集合。

我真的不知道为什么。我不认为我运行相抵触的器具裁定的帮助文件也解释了。下面是IDL类型库(幸运的是,这是一个短期的)。任何人都可以看到什么是错的,是造成这此类型库?

编辑:--------------------------------

记住,我有几个版本,此组件的COM版本之前,我比较了IDL,注意就可以了,这两个接口被标记的不可扩展。这是相关的WithEvents就失败?当我使用的组件,而不是新的,它不会失败在新和正确接收事件

我看到的唯一区别是href="http://msdn.microsoft.com/en-us/library/hk3bk11y.aspx" rel="nofollow">隐藏属性和的

从.NET .TLB

  //生成.IDL文件(由OLE / COM对象查看器)
//
//类型库文件名:图纸Locator.tlb

[
  UUID(4ABD3AAB-CA6A-48D6-8E4E-8082645A0F05)
  版本(1.0),
  自定义(90883F05-3D28-11D2-8F17-00A0C9A6186D,绘图定位器,版本= 1.0.0.0,文化=中性公钥= e02c23b3671cff4d)

]
库Drawing_Locator
{
    // TLib:/​​/ TLib:mscorlib.dll中:{BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}
    导入库(mscorlib.tlb);
    // TLib:OLE自动化:{00020430-0000-0000-C000-000000000046}
导入库(STDOLE2.TLB);

//转发声明在此类型库中定义的所有类型
接口IDrawingFinder;
调度接口IDrawingFinderEvents;

的typedef [UUID(565D6F5A-13BF-4794-AC35-3ECC4329B280),版本(1.0)
  定制(0F21F359-AB84-41E8-9A78-36D110E6D2F9,Drawing_Locator.FileTypes)
]
枚举{
    FileTypes_Tiff = 0,
    FileTypes_Acad = 1
}文件类型;

[
  UUID(78B2A29B-C289-4D65-B373-C345AD06BD31)
  版本(1.0),
  定制(0F21F359-AB84-41E8-9A78-36D110E6D2F9,Drawing_Locator.DrawingFinder)
]
组件类DrawingFinder {
    接口_Object;
    [默认]接口IDrawingFinder;
    [默认情况下,源]调度接口IDrawingFinderEvents;
};

[
  ODL,
  UUID(21DBD6E1-D04F-4335-B189-5B49EB960605)
  版本(1.0),
  双重,
  了oleautomation,
  定制(0F21F359-AB84-41E8-9A78-36D110E6D2F9,Drawing_Locator.IDrawingFinder)

]
接口IDrawingFinder:IDispatch接口{
    [ID(0x60020000)]
    HRESULT的GetFiles(
                    [中] BSTR型号,
                    [IN]的文件类型的文件类型,
                    [中] VARIANT_BOOL openFiles散,
                    [出,RETVAL] SAFEARRAY(BSTR)* pretVal);
    [ID(0x60020001)]
    HRESULT RegisterTiffToImaging();
};

[
  UUID(60314738-04D1-4B4A-BC39-6A81DE24A13B)
  版本(1.0),
  定制(0F21F359-AB84-41E8-9A78-36D110E6D2F9,Drawing_Locator.IDrawingFinderEvents)

]
调度接口IDrawingFinderEvents {
    特性:
    方法:
        [ID(00000001)]
        无效PartNumberChanged([中] BSTR NewPartNumber);
        [ID(0x00000002)]
        无效搜索([IN,OUT] VARIANT_BOOL * CancelSearch);
};
};
 

在.NET侧的 code:

 导入了System.Runtime.InteropServices

<标记有ComVisible特性(真)>
< InterfaceType(ComInterfaceType.InterfaceIsDual)>
<的Guid(21DBD6E1-D04F-4335-B189-5B49EB960605)>
公共接口IDrawingFinder

功能的GetFiles(BYVAL型号作为字符串,BYVAL文件类型的文件类型,如,BYVAL openFiles散作为布尔)为<的MarshalAs(UnmanagedType.SafeArray,SafeArraySubType:= VarEnum.VT_BSTR)>串()

子RegisterTiffToImaging()

结束接口



<标记有ComVisible特性(真)>
< InterfaceType(ComInterfaceType.InterfaceIsIDispatch)>
<的Guid(60314738-04D1-4B4A-BC39-6A81DE24A13B)>
公共接口IDrawingFinderEvents

&其中; System.Runtime.InteropServices.DispId(1)>
子PartNumberChanged(BYVAL NewPartNumber作为字符串)

&其中; System.Runtime.InteropServices.DispId(2)及GT;
子搜索(为ByRef CancelSearch作为布尔)

结束接口

<标记有ComVisible特性(真)>
< GuidAttribute(565D6F5A-13BF-4794-AC35-3ECC4329B280)>
公共枚举文件类型
斗嘴
科学院
结束枚举

< System.Runtime.InteropServices.ComVisible(假)>
公共委托子OnPartNumberChanged(BYVAL NewPartNumber作为字符串)
< System.Runtime.InteropServices.ComVisible(假)>
公共委托子OnSearching(为ByRef CancelSearch作为布尔)


<标记有ComVisible特性(真)>
< ClassInterface(ClassInterfaceType.None)>
< ComDefaultInterface(的GetType(Drawing_Locator.IDrawingFinder))>
< ComSourceInterfaces(的GetType(Drawing_Locator.IDrawingFinderEvents))>
< GuidAttribute(78B2A29B-C289-4D65-B373-C345AD06BD31)>
公共类DrawingFinder
实现IDrawingFinder


公共事件PartNumberChanged作为OnPartNumberChanged

公共事件搜索作为OnSearching


事件PartNumberChanged(BYVAL NewPartNumber作为字符串)
事件搜索(为ByRef CancelSearch作为布尔)

私人声明子SHAddToRecentDocs库SHELL32.DLL(BYVAL和uFlags为整数,光伏BYVAL作为字符串)
私人常量SHARD_PATH作为整数= 2

昏暗的工人由于BackgroundWorker的
昏暗的EventArgs作为DoWorkEventArgs




公共职能的GetFiles(BYVAL型号作为字符串,BYVAL文件类型的文件类型,如,BYVAL openFiles散由于布尔)作为字符串()实现IDrawingFinder.GetFiles

结束小组

末级
 

从VB6旧的(工作).TLB

  //类型库文件名:DrawingFinder.dll

[
UUID(D11F3F87-F149-4060-81D3-F46A90DA28CB)
版本(1.0),
helpstring(查找并打开工程图),
定制(50867B00-BB69-11D0-A8FF-00A0C9110059,9782)

]
库DrawingSearch
{
// TLib:/​​/ TLib:OLE自动化:{00020430-0000-0000-C000-000000000046}
导入库(STDOLE2.TLB);

//转发声明在此类型库中定义的所有类型
接口_DrawingFinder;
调度接口__DrawingFinder;

[
  ODL,
  UUID(A0AB1327-59A7-45E0-8992-92DB8253368B)
  版本(1.0),
  隐,
  双重,
  不可扩展,
  了oleautomation
  ]
  接口_DrawingFinder:IDispatch接口{
    [ID(0x60030000)]
    HRESULT OpenAcadDwgs([中] BSTR PN);
    [ID(0x60030001)]
    HRESULT OpenImageFiles([中] BSTR PN);
    [ID(0x60030002)]
    HRESULT GetAcadDwgs(
                    [中] BSTR PN,
                    [出,RETVAL] SAFEARRAY(BSTR)*);
    [ID(0x60030003)]
    HRESULT GetImageFiles(
                    [中] BSTR PN,
                    [出,RETVAL] SAFEARRAY(BSTR)*);
};

[
  UUID(95E5F4E3-6A45-4B60-845B-3A78E75A8319)
  版本(1.0)
]
组件类DrawingFinder {
    [默认]接口_DrawingFinder;
    [默认情况下,源]调度接口__DrawingFinder;
};

[
  UUID(BB78905B-297B-4D7C-80B0-3297D4B07AFE)
  版本(1.0),
  隐,
  不可扩展
]
调度接口__DrawingFinder {
    特性:
    方法:
        [ID(00000001)]
        无效搜索([IN,OUT] VARIANT_BOOL *取消);
        [ID(0x00000002)]
        无效PartNumberChanged([中] BSTR FormattedPN);
};

的typedef [UUID(4F3E20EC-EE21-40E8-813F-9292605EF941),版本(1.0)]
枚举{
    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;
};
 

解决方案

我编译.NET版本,然后使用OLEVIEW来无论从.NET和COM VB6版本生成code的TLB。

那么在类似BeyondCompare或Araxis对它们进行比较。

获取所有列队的GUID,然后寻找其他不同之处。

没有什么是从什么贴跳出我,但我已经花了大量的时间比较的TLB,以获得.NET版本刚刚好。

我不知道礼仪对SO有关张贴链接,但我做了一个项目,前段时间启用书签和断点保存在VB6。这是生成的COM插件的VB6 IDE一个VB.net的项目,所以有​​对COM互操作例如code地段在那里。

看看这里:

的https://bookmarksavevb6.$c$cplex.com/

I am attempting to raise an event in .NET and have it picked up through COM by a VBA application. This answer has been quite helpful in getting my events to show up properly in the type library.

On the VBA side, everything looks legit. I have an object variable declared "WithEvents" ,the IDE lets me add event handlers, and the compiler doesn't complain. However at run-time, when I use New to create the object I get the Run-time error 459: This component doesn't support this set of events. According to the help file , this means: "You tried to use a WithEvents variable with a component that can't work as an event source for the specified set of events."

I do not really know why. I do not think I am running afoul of the Implements rule that the help file also explains. Below is the IDL for the type library (luckily it is a short one). Can anyone see what is wrong with this type library that is causing this?

EDIT : --------------------------------

Remembering that I had a COM version of this component from several versions ago, I compared its IDL and notice that on it, both interfaces are marked nonextensible. Is this relevant to the WithEvents failure? When I use that component instead of the new one, it does not fail at "New" and receives events properly.

The only other differences I see are the hidden attribute and the double underscore naming for the event interface (and why would either of those matter?)

.tlb from .NET

// 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);
};
};

code on the .NET side:

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

the old (working) .tlb from VB6

// 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;
};

解决方案

I'd compile the .net version, then use OLEVIEW to generate the code for the TLB from both the .net and the COM VB6 versions.

Then compare them in something like BeyondCompare or Araxis.

Get the GUIDs all lined up, and then look for any other differences.

Nothing's jumping out at me from what's posted, but I've spent plenty of time comparing TLBs in order to get the .net version "just right".

I'm not sure of the etiquette on SO about posting links, but I did a project some time ago that enabled Bookmark and breakpoint saving in VB6. It was a VB.net project that generated a COM addin for the VB6 IDE, so there's LOTS of COM interop example code in there.

Check it out here:

https://bookmarksavevb6.codeplex.com/

这篇关于WithEvents就错误下沉来自一个.NET组件COM事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆