“添加事件处理程序失败”处理来自 COM 的事件时

发布于 2024-11-18 16:45:23 字数 2769 浏览 1 评论 0原文

我有一个 COM 服务器和一个调用它的 Silverlight (OOTB) 应用程序。我最近对 ​​COM 服务器进行了一些重构,我设法破坏了服务器和客户端之间的事件处理,但我不知道如何破坏它。这是我现在所拥有的:

服务器

namespace ServerNS
{
    [Guid("8FFF7AAE-B162-42C2-9F70-269D285CF622")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    [ComVisible(true)]
    interface IServerEvents
    {
        [DispId(1)]
        void MyEvent(MyContainer container);
    }

    [Guid("D2F3738D-DD23-472F-9D36-4136E1196890")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    [ComVisible(true)]
    public interface IServer
    {
        ...
    }

    [Guid("77253016-1A2A-43CC-A360-04519A4F50F5")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComSourceInterfaces(typeof(IServerEvents))]
    [ProgId("Server.MyServer")]
    [ComVisible(true)]
    public class Server : IServer
    {
        public event MyEventHandler MyEvent;

        public void Trigger(MyContainer container)
        {
            if (MyEvent != null)
            {
                MyEvent(container);
            }
        }
    }
}

客户端

namespace ClientNS
{
    public class Client
    {
        public void Init()
        {
            dynamic comObj = AutomationFactory.CreateObject("Server.MyServer");
            AutomationEvent evt = AutomationFactory.GetEvent(comObj, "MyEvent");

            evt.EventRaised += (sender, e) =>
            {
                //Do Stuff
            }; //Exception occurs here.
        }
    }
}

错误 当我尝试将事件处理程序添加到 AutomationEvent 时,出现此异常。这在我重构(添加 IServerEvents 接口)之前就有效了。 comObj 是一个合法的实例 - 我可以在其上调用其他 COM 方法 - 所以我无法弄清楚为什么它似乎找不到该事件;或者如果这是错误的“某件事失败”部分,如何找出失败的原因。

System.Exception was unhandled by user code
  Message=Failed to add event handler. Possible reasons include: the object does not support this or any events, or something failed while adding the event.
  StackTrace:
       at MS.Internal.Error.MarshalXresultAsException(UInt32 hr, COMExceptionBehavior comExceptionBehavior)
       at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
       at MS.Internal.ComAutomation.ComAutomationNative.ConnectEvent(IntPtr nativePeer, String eventName, RaiseComAutomationEventDelegate raiseComAutomationEventDelegate)
       at MS.Internal.ComAutomation.ComAutomationObject.ConnectEvent(String name)
       at System.Runtime.InteropServices.Automation.AutomationEvent.UpdateConnection()
       at System.Runtime.InteropServices.Automation.AutomationEvent.add_EventRaised(EventHandler`1 value)
       at ClientNS.Client.Init()
       at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
       at System.ComponentModel.BackgroundWorker.OnRun(Object argument)

I have a COM server, and a Silverlight (OOTB) app that calls it. I recently did a bit of refactoring of the COM server, and I managed to break event handling between the server and the client, and I can't figure out how I broke it. Here's what I have now:

Server

namespace ServerNS
{
    [Guid("8FFF7AAE-B162-42C2-9F70-269D285CF622")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    [ComVisible(true)]
    interface IServerEvents
    {
        [DispId(1)]
        void MyEvent(MyContainer container);
    }

    [Guid("D2F3738D-DD23-472F-9D36-4136E1196890")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    [ComVisible(true)]
    public interface IServer
    {
        ...
    }

    [Guid("77253016-1A2A-43CC-A360-04519A4F50F5")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComSourceInterfaces(typeof(IServerEvents))]
    [ProgId("Server.MyServer")]
    [ComVisible(true)]
    public class Server : IServer
    {
        public event MyEventHandler MyEvent;

        public void Trigger(MyContainer container)
        {
            if (MyEvent != null)
            {
                MyEvent(container);
            }
        }
    }
}

Client

namespace ClientNS
{
    public class Client
    {
        public void Init()
        {
            dynamic comObj = AutomationFactory.CreateObject("Server.MyServer");
            AutomationEvent evt = AutomationFactory.GetEvent(comObj, "MyEvent");

            evt.EventRaised += (sender, e) =>
            {
                //Do Stuff
            }; //Exception occurs here.
        }
    }
}

Error
I'm getting this exception when I try to add the event handler to the AutomationEvent. This worked before my refactoring (which was to add the IServerEvents interface). comObj is a legitimate instance - I can call other COM methods on it - so I can't figure out why it can't seem to find that event; or if it's the "something failed" part of the error, how to figure out what failed.

System.Exception was unhandled by user code
  Message=Failed to add event handler. Possible reasons include: the object does not support this or any events, or something failed while adding the event.
  StackTrace:
       at MS.Internal.Error.MarshalXresultAsException(UInt32 hr, COMExceptionBehavior comExceptionBehavior)
       at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
       at MS.Internal.ComAutomation.ComAutomationNative.ConnectEvent(IntPtr nativePeer, String eventName, RaiseComAutomationEventDelegate raiseComAutomationEventDelegate)
       at MS.Internal.ComAutomation.ComAutomationObject.ConnectEvent(String name)
       at System.Runtime.InteropServices.Automation.AutomationEvent.UpdateConnection()
       at System.Runtime.InteropServices.Automation.AutomationEvent.add_EventRaised(EventHandler`1 value)
       at ClientNS.Client.Init()
       at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
       at System.ComponentModel.BackgroundWorker.OnRun(Object argument)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

落花浅忆 2024-11-25 16:45:23

事实证明,问题在于该接口未声明为“公共” - 因此接口需要如下所示:

public interface IServerEvents
{
    [DispId(1)]
    void MyEvent(MyContainer container);
}

It turns out that the issue was that the interface was not declared "public" - so the interface needed to look like this:

public interface IServerEvents
{
    [DispId(1)]
    void MyEvent(MyContainer container);
}
醉酒的小男人 2024-11-25 16:45:23
//DHTMLEventHandler.cs 

using System.Runtime.InteropServices;
using mshtml;

namespace BHO
{
    /// 
    /// Generic Event handler for HTML DOM objects.
    /// Handles a basic event object which receives an IHTMLEventObj which
    /// applies to all document events raised.
    /// 

[ComVisible(true)]
public class DHTMLEventHandler
{
    public DHTMLEvent Handler;
    IHTMLDocument2 Document;


    public DHTMLEventHandler(IHTMLDocument2 doc)
    {
        this.Document = doc;
    }
    [DispId(0)]
    public void Call()
    {
        Handler(Document.parentWindow.@event);
    }
}

/// 
/// Generic HTML DOM Event method handler.
/// 
public delegate void DHTMLEvent(IHTMLEventObj e);

添加

在OnDocumentComplete中

IHTMLElement htmlElement = document.getElementById("ele");
DHTMLEventHandler Handler = new DHTMLEventHandler((IHTMLDocument2)webBrowser.Document);
Handler.Handler += new DHTMLEvent(Dummy_OnClick);
htmlElement.onclick = Handler;

新方法来处理点击事件

void Dummy_OnClick(IHTMLEventObj e){
// DO Action 
}
//DHTMLEventHandler.cs 

using System.Runtime.InteropServices;
using mshtml;

namespace BHO
{
    /// 
    /// Generic Event handler for HTML DOM objects.
    /// Handles a basic event object which receives an IHTMLEventObj which
    /// applies to all document events raised.
    /// 

[ComVisible(true)]
public class DHTMLEventHandler
{
    public DHTMLEvent Handler;
    IHTMLDocument2 Document;


    public DHTMLEventHandler(IHTMLDocument2 doc)
    {
        this.Document = doc;
    }
    [DispId(0)]
    public void Call()
    {
        Handler(Document.parentWindow.@event);
    }
}

/// 
/// Generic HTML DOM Event method handler.
/// 
public delegate void DHTMLEvent(IHTMLEventObj e);

}

In OnDocumentComplete

IHTMLElement htmlElement = document.getElementById("ele");
DHTMLEventHandler Handler = new DHTMLEventHandler((IHTMLDocument2)webBrowser.Document);
Handler.Handler += new DHTMLEvent(Dummy_OnClick);
htmlElement.onclick = Handler;

Add new method to handle click event

void Dummy_OnClick(IHTMLEventObj e){
// DO Action 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文