HighTechTalks DotNet Forums  

Events in Managed COM

Dotnet Framework (Interop) microsoft.public.dotnet.framework.interop


Discuss Events in Managed COM in the Dotnet Framework (Interop) forum.



Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old   
Ken Ross
 
Posts: n/a

Default Events in Managed COM - 05-19-2010 , 01:10 PM






We've created a COM component in C# which needs to be able to raise
events to a managed code consumer of the COM component (Silverlight 4 in
this case). We can call methods on the COM component just fine but when
we try to register the event handler it throws and gives an error
indicating it can't find the event we're specifying.

As an asside, it would be GREAT to be able to test this outside of SL
with a console app or unit test, but when we try to reference the
managed COM component from a non-Silverlight managed client, the IDE
barks and tells us to just add a reference to the assembly [instead of
using COM].

Here's the code we're using to defne the event on the COM component
side:

namespace DeviceCom
{
public delegate void DeviceEventHandler(object sender,
DeviceEventArgs e);

public class DeviceEventArgs : EventArgs
{
public string Data { get; set; }

public DeviceEventArgs() { }

public DeviceEventArgs(string data)
{
Data = data;
}
}
}


The event Interface looks like this:

namespace DeviceCom
{
[Guid("7E1E5F7D-3303-4A15-8025-CB8458AF1949"),
InterfaceType(ComInterfaceType.InterfaceIsIDispatc h)]
public interface IDeviceComEvents
{
event DeviceEventHandler LeftLineDataReceived;
}
}


The COM object that raises the event (and implements the above
interface):

namespace DeviceCom
{
[Guid("38814898-A470-42DE-AD21-9AB29B5A536E"),
ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(IDeviceComEvents))]
public class DeviceComManager : DeviceCom.IDeviceComManager
{
public DeviceComManager() { }

public void InitializeDevices()
{
DeviceInformation deviceInfo = new DeviceInformation("Left
Line Pin",
"COM3,9600,N,8,1",
"/HORIZON",
false, 1, 1, true, CommunicationStyles.Horizon,
DeviceManager.CashDrawerType.None);

List<DeviceInformation> deviceList = new
List<DeviceInformation>(); deviceList.Add(deviceInfo);

DeviceManager.InitializeDevices(deviceList);
DeviceManager.LeftLineDataReceived +=new
DeviceManager.LeftLineDataReceivedEventHandler(Dev iceManager_
LeftLineDataReceived);

}

public string HelloWorld()
{
return "Hello World";
}

private void DeviceManager_LeftLineDataReceived(object sender,
DeviceArgs e) {
LeftLineDataReceived(this, new
DeviceEventArgs(e.DataReceived));
}

public event DeviceEventHandler LeftLineDataReceived;
}
}


And here's the line that throws when we try to handle the event on the
Silverlight side:

public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}

private void Button_Click(object sender, RoutedEventArgs e)
{
Go();
}

private void Go()
{
dynamic device =
AutomationFactory.CreateObject("DeviceCom.DeviceCo mManager");
device.InitializeDevices();

AutomationEvent hzDeviceEvent =
AutomationFactory.GetEvent(device, "LeftLineDataReceived");

//****>> This next line throws!
hzDeviceEvent.EventRaised += (sender, e) =>
{
MessageBox.Show((string)e.Arguments[0]);
};

string hw = device.HelloWorld();
if (hw != null)
{
MessageBox.Show(hw);
}
}

void hzDeviceEvent_EventRaised(object sender,
AutomationEventArgs e) {
MessageBox.Show((string)e.Arguments[0]);
}

}


Lastly, here is the exception that the above event registration throws:

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.Conn ectEvent(IntPtr
nativePeer, String eventName, RaiseComAutomationEventDelegate
raiseComAutomationEventDelegate) at
MS.Internal.ComAutomation.ComAutomationObject.Conn ectEvent(String
name) at
System.Runtime.InteropServices.Automation.Automati onEvent.UpdateCo
nnection() at
System.Runtime.InteropServices.Automation.Automati onEvent.add_Even
tRaised(EventHandler`1 value) at
SilverlightApplication1.MainPage.Go() at
SilverlightApplication1.MainPage.Button_Click(Obje ct sender,
RoutedEventArgs e) at
System.Windows.Controls.Primitives.ButtonBase.OnCl ick() at
System.Windows.Controls.Button.OnClick() at
System.Windows.Controls.Primitives.ButtonBase.OnMo useLeftButtonUp(
MouseButtonEventArgs e) at
System.Windows.Controls.Control.OnMouseLeftButtonU p(Control ctrl,
EventArgs e) at MS.Internal.JoltHelper.FireEvent(IntPtr
unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex,
String eventName)

Reply With Quote
  #2  
Old   
TDC
 
Posts: n/a

Default Re: Events in Managed COM - 05-20-2010 , 03:00 PM






On your aside, you must have tried to add a ref to the tlb exported
from your .NET based COM component from Visual Studio. The tlb
exported from .NET contains a flag that states it came from .NET. If
you are trying to test your .NET COM object from a real COM client,
try a simple VBScript or VB6 program.



On May 19, 2:10*pm, Ken Ross <kr... (AT) horizonsoftware (DOT) com> wrote:
Quote:
We've created a COM component in C# which needs to be able to raise
events to a managed code consumer of the COM component (Silverlight 4 in
this case). We can call methods on the COM component just fine but when
we try to register the event handler it throws and gives an error
indicating it can't find the event we're specifying.

As an asside, it would be GREAT to be able to test this outside of SL
with a console app or unit test, but when we try to reference the
managed COM component from a non-Silverlight managed client, the IDE
barks and tells us to just add a reference to the assembly [instead of
using COM].

Here's the code we're using to defne the event on the COM component
side:

namespace DeviceCom
{
* * public delegate void DeviceEventHandler(object sender,
* * DeviceEventArgs e);

* * public class DeviceEventArgs : EventArgs
* * {
* * * * public string Data { get; set; }

* * * * public DeviceEventArgs() { }

* * * * public DeviceEventArgs(string data)
* * * * {
* * * * * * Data = data;
* * * * }
* * }

}

The event Interface looks like this:

namespace DeviceCom
{
* * [Guid("7E1E5F7D-3303-4A15-8025-CB8458AF1949"),
* * InterfaceType(ComInterfaceType.InterfaceIsIDispatc h)]
* * public interface IDeviceComEvents
* * {
* * * * event DeviceEventHandler LeftLineDataReceived;
* * }

}

The COM object that raises the event (and implements the above
interface):

namespace DeviceCom
{
* * [Guid("38814898-A470-42DE-AD21-9AB29B5A536E"),
* * ClassInterface(ClassInterfaceType.None),
* * ComSourceInterfaces(typeof(IDeviceComEvents))]
* * public class DeviceComManager : DeviceCom.IDeviceComManager
* * {
* * * * public DeviceComManager() { }

* * * * public void InitializeDevices()
* * * * {
* * * * * * DeviceInformation deviceInfo = new DeviceInformation("Left
* * * * * * Line Pin",
* * * * * * * * "COM3,9600,N,8,1",
* * * * * * * * "/HORIZON",
* * * * * * * * false, 1, 1, true, CommunicationStyles.Horizon,
* * * * * * * * DeviceManager.CashDrawerType.None);

* * * * * * List<DeviceInformation> deviceList = new
* * * * * * List<DeviceInformation>(); deviceList.Add(deviceInfo);

* * * * * * DeviceManager.InitializeDevices(deviceList);
* * * * * * DeviceManager.LeftLineDataReceived +=new
* * * * * * DeviceManager.LeftLineDataReceivedEventHandler(Dev iceManager_
* * * * * * LeftLineDataReceived);

* * * * }

* * * * public string HelloWorld()
* * * * {
* * * * * * return "Hello World";
* * * * }

* * * * private void DeviceManager_LeftLineDataReceived(object sender,
* * * * DeviceArgs e) {
* * * * * * LeftLineDataReceived(this, new
* * * * * * DeviceEventArgs(e.DataReceived));
* * * * }

* * * * public event DeviceEventHandler LeftLineDataReceived;
* * }

}

And here's the line that throws when we try to handle the event on the
Silverlight side:

* * public partial class MainPage : UserControl
* * {
* * * * public MainPage()
* * * * {
* * * * * * InitializeComponent();
* * * * }

* * * * private void Button_Click(object sender, RoutedEventArgs e)
* * * * {
* * * * * * Go();
* * * * }

* * * * private void Go()
* * * * {
* * * * * * dynamic device =
* * * * * * AutomationFactory.CreateObject("DeviceCom.DeviceCo mManager");
* * * * * * device.InitializeDevices();

* * * * * * AutomationEvent hzDeviceEvent =
* * * * * * AutomationFactory.GetEvent(device, "LeftLineDataReceived");

//****>> This next line throws!
* * * * * * hzDeviceEvent.EventRaised += (sender, e) =
* * * * * * {
* * * * * * * * MessageBox.Show((string)e.Arguments[0]);
* * * * * * };

* * * * * * string hw = device.HelloWorld();
* * * * * * if (hw != null)
* * * * * * {
* * * * * * * * MessageBox.Show(hw);
* * * * * * }
* * * * }

* * * * void hzDeviceEvent_EventRaised(object sender,
* * * * AutomationEventArgs e) {
* * * * * * MessageBox.Show((string)e.Arguments[0]);
* * * * }

* * }

Lastly, here is the exception that the above event registration throws:

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.Con nectEvent(IntPtr
* * * *nativePeer, String eventName, RaiseComAutomationEventDelegate
* * * *raiseComAutomationEventDelegate) at
* * * *MS.Internal.ComAutomation.ComAutomationObject.Con nectEvent(String
* * * *name) at
* * * *System.Runtime.InteropServices.Automation.Automat ionEvent.UpdateCo
* * * *nnection() at
* * * *System.Runtime.InteropServices.Automation.Automat ionEvent.add_Even
* * * *tRaised(EventHandler`1 value) at
* * * *SilverlightApplication1.MainPage.Go() at
* * * *SilverlightApplication1.MainPage.Button_Click(Obj ect sender,
* * * *RoutedEventArgs e) at
* * * *System.Windows.Controls.Primitives.ButtonBase.OnC lick() at
* * * *System.Windows.Controls.Button.OnClick() at
* * * *System.Windows.Controls.Primitives.ButtonBase.OnM ouseLeftButtonUp(
* * * *MouseButtonEventArgs e) at
* * * *System.Windows.Controls.Control.OnMouseLeftButton Up(Control ctrl,
* * * *EventArgs e) at MS.Internal.JoltHelper.FireEvent(IntPtr
* * * *unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex,
* * * *String eventName)

Reply With Quote
  #3  
Old   
Craig Berntson
 
Posts: n/a

Default Re: Events in Managed COM - 05-24-2010 , 10:35 AM



Look at the Forms Interop Toolkit. MS has one for VB.NET. There is a
community created one for C#.

--

----
Craig Berntson
Microsoft MVP

"Ken Ross" <kross (AT) horizonsoftware (DOT) com> wrote

Quote:
We've created a COM component in C# which needs to be able to raise
events to a managed code consumer of the COM component (Silverlight 4 in
this case). We can call methods on the COM component just fine but when
we try to register the event handler it throws and gives an error
indicating it can't find the event we're specifying.

As an asside, it would be GREAT to be able to test this outside of SL
with a console app or unit test, but when we try to reference the
managed COM component from a non-Silverlight managed client, the IDE
barks and tells us to just add a reference to the assembly [instead of
using COM].

Here's the code we're using to defne the event on the COM component
side:

namespace DeviceCom
{
public delegate void DeviceEventHandler(object sender,
DeviceEventArgs e);

public class DeviceEventArgs : EventArgs
{
public string Data { get; set; }

public DeviceEventArgs() { }

public DeviceEventArgs(string data)
{
Data = data;
}
}
}


The event Interface looks like this:

namespace DeviceCom
{
[Guid("7E1E5F7D-3303-4A15-8025-CB8458AF1949"),
InterfaceType(ComInterfaceType.InterfaceIsIDispatc h)]
public interface IDeviceComEvents
{
event DeviceEventHandler LeftLineDataReceived;
}
}


The COM object that raises the event (and implements the above
interface):

namespace DeviceCom
{
[Guid("38814898-A470-42DE-AD21-9AB29B5A536E"),
ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(IDeviceComEvents))]
public class DeviceComManager : DeviceCom.IDeviceComManager
{
public DeviceComManager() { }

public void InitializeDevices()
{
DeviceInformation deviceInfo = new DeviceInformation("Left
Line Pin",
"COM3,9600,N,8,1",
"/HORIZON",
false, 1, 1, true, CommunicationStyles.Horizon,
DeviceManager.CashDrawerType.None);

List<DeviceInformation> deviceList = new
List<DeviceInformation>(); deviceList.Add(deviceInfo);

DeviceManager.InitializeDevices(deviceList);
DeviceManager.LeftLineDataReceived +=new
DeviceManager.LeftLineDataReceivedEventHandler(Dev iceManager_
LeftLineDataReceived);

}

public string HelloWorld()
{
return "Hello World";
}

private void DeviceManager_LeftLineDataReceived(object sender,
DeviceArgs e) {
LeftLineDataReceived(this, new
DeviceEventArgs(e.DataReceived));
}

public event DeviceEventHandler LeftLineDataReceived;
}
}


And here's the line that throws when we try to handle the event on the
Silverlight side:

public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}

private void Button_Click(object sender, RoutedEventArgs e)
{
Go();
}

private void Go()
{
dynamic device =
AutomationFactory.CreateObject("DeviceCom.DeviceCo mManager");
device.InitializeDevices();

AutomationEvent hzDeviceEvent =
AutomationFactory.GetEvent(device, "LeftLineDataReceived");

//****>> This next line throws!
hzDeviceEvent.EventRaised += (sender, e) =
{
MessageBox.Show((string)e.Arguments[0]);
};

string hw = device.HelloWorld();
if (hw != null)
{
MessageBox.Show(hw);
}
}

void hzDeviceEvent_EventRaised(object sender,
AutomationEventArgs e) {
MessageBox.Show((string)e.Arguments[0]);
}

}


Lastly, here is the exception that the above event registration throws:

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.Conn ectEvent(IntPtr
nativePeer, String eventName, RaiseComAutomationEventDelegate
raiseComAutomationEventDelegate) at
MS.Internal.ComAutomation.ComAutomationObject.Conn ectEvent(String
name) at
System.Runtime.InteropServices.Automation.Automati onEvent.UpdateCo
nnection() at
System.Runtime.InteropServices.Automation.Automati onEvent.add_Even
tRaised(EventHandler`1 value) at
SilverlightApplication1.MainPage.Go() at
SilverlightApplication1.MainPage.Button_Click(Obje ct sender,
RoutedEventArgs e) at
System.Windows.Controls.Primitives.ButtonBase.OnCl ick() at
System.Windows.Controls.Button.OnClick() at
System.Windows.Controls.Primitives.ButtonBase.OnMo useLeftButtonUp(
MouseButtonEventArgs e) at
System.Windows.Controls.Control.OnMouseLeftButtonU p(Control ctrl,
EventArgs e) at MS.Internal.JoltHelper.FireEvent(IntPtr
unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex,
String eventName)

Reply With Quote
Reply




Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.