2011-07-06 185 views
1

我有一個COM服務器和一個調用它的Silverlight(OOTB)應用程序。我最近做了一些COM服務器的重構,並且設法中斷服務器和客戶端之間的事件處理,但我無法弄清楚我是如何破壞它的。這是我現在有:處理來自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) 

回答

0

事實證明,這個問題是該接口未聲明 「公共」 - 所以需要的界面看起來像這樣:

public interface IServerEvents 
{ 
    [DispId(1)] 
    void MyEvent(MyContainer container); 
} 
0
//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([email protected]); 
    } 
} 

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