EventHandler for late-bound COM object

P

Phil

I'm trying to handle an event from a late-bound COM object.
Here is my code so far:

Dim t As Type = o.GetType()
Dim eInfo As EventInfo = t.GetEvent(EventName)
Dim d As New MyDelegate(AddressOf MyHandler)
eInfo.AddEventHandler(o, d)

However this fails as GetEvent is returning Nothing.
The problem appears to be that GetType is returning a __ComObject rather
than the underlying COM object itself, so it can't find the event.
Is there a way of getting the events for the COM object?
Or is there a better way to do this?

TIA
Phil
 
J

Jialiang Ge [MSFT]

Hello Phil,

From your post, my understanding on this issue is: you wonder why your COM
object does not expose its events in late binding and how to resolve it. If
I'm off base, please feel free to let me know.

According to your sample code, I think you are using VB.*NET*. In order to
get all the events of a COM object with .net Reflection, we could call
GetEvents() method on a System.Type object. In this post, it seems that
GetEvents() returns an empty array. As you said, it is because the object
type is System.__ComObject, and it does not expose any real type
information. .NET Reflection generally only understands managed metadata,
not COM's ITypeInfo. In order to let it discover the COM events, we need a
managed description of the COM types in an interop assembly, which is
called RCW. I did the following test to reproduce your issue:

As we know, we need Office Primary Interop Assembly (PIA) to automate
Office in .NET. If the PIA has already been installed, the line
CreateObject("Word.Application") will return an object of type:
Word.Application, and the call of Type.GetEvents() will return all the
public events of the word application object. But if we uninstall the
Office PIA and try the CreateObject again, it only returns a
System.__ComObject object and no event is returned in GetEvents() call.

To resolve the problem:

1. If the COM component is a self-designed one, we could manually create a
..net interop assembly by running tlbimp command on it. Then add the
reference to the primary dll in your project.
For more information about how to create a .net interop assembly, please
refer to the MSDN article
http://msdn2.microsoft.com/en-US/library/tw4zwhbe.aspx
2. If the COM component belongs to a product, like the COM component of
Office, we could search for their .NET PIA from product owner and install
the PIA in your computer.
3. If the COM component has no way to be retrieved, you may consider hook
up the events via IConnectionPoint interfaces. The KB article
http://support.microsoft.com/kb/811645/en-us gives an example. For more
information about COM events in .NET, please refer to
http://msdn2.microsoft.com/en-us/library/1hee64c7(VS.71).aspx

Please let me know if you have any other concerns, or need anything else.

Sincerely,
Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
For MSDN subscribers whose posts are left unanswered, please check this
document: http://blogs.msdn.com/msdnts/pages/postingAlias.aspx

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications. If you are using Outlook Express/Windows Mail, please make sure
you clear the check box "Tools/Options/Read: Get 300 headers at a time" to
see your reply promptly.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
P

Phil

From your post, my understanding on this issue is: you wonder why your COM
object does not expose its events in late binding and how to resolve it.
If
I'm off base, please feel free to let me know.

That's basically it, yes.
According to your sample code, I think you are using VB.*NET*.

Correct. That's why I posted the question in the VB.NET ng :)
I've just upgraded from VB 2005 Express to the Professional Edition.
My previous experience is mostly with VB6 though, so I am unfamiliar with
many of the new concepts in .NET.
In order to
get all the events of a COM object with .net Reflection, we could call
GetEvents() method on a System.Type object. In this post, it seems that
GetEvents() returns an empty array.

Actually it returns 'Nothing' rather than an empty array, but you're right,
I don't see the events that I had hoped to see..
As you said, it is because the object
type is System.__ComObject, and it does not expose any real type
information. .NET Reflection generally only understands managed metadata,
not COM's ITypeInfo. In order to let it discover the COM events, we need a
managed description of the COM types in an interop assembly, which is
called RCW. I did the following test to reproduce your issue:

OK. I guess I need to read up on Interop assemblies.
As we know, we need Office Primary Interop Assembly (PIA) to automate
Office in .NET.

Actually I didn't know that.
If the PIA has already been installed, the line
CreateObject("Word.Application") will return an object of type:
Word.Application, and the call of Type.GetEvents() will return all the
public events of the word application object. But if we uninstall the
Office PIA and try the CreateObject again, it only returns a
System.__ComObject object and no event is returned in GetEvents() call.

In this particular case I am automating Excel rather than Word, but it's
essentially the same thing. I did originally add a reference to Excel to my
project, but I don't want my application to be reliant on Office being
installed on the target system, so I chose to use late-binding. I can use
CreateObject to start an Excel Application instance, and can call methods
and properties, no problem. I don't think I need the PIA to do this do I? I
have had it running on several different machines, without installing this
PIA. I suppose it's possible, that it's already installed? How can I check
this?
It seems odd that I can access all the properties and methods, but not the
events.
To resolve the problem:

1. If the COM component is a self-designed one, we could manually create a
.net interop assembly by running tlbimp command on it. Then add the
reference to the primary dll in your project.
For more information about how to create a .net interop assembly, please
refer to the MSDN article
http://msdn2.microsoft.com/en-US/library/tw4zwhbe.aspx

At the moment, I am just using Excel objects, but I'll perhaps take a look
at this for future reference.
I want to avoid adding a reference to my project though, because I need it
to run even if the COM component is not installed (albeit with reduced
functionality).
2. If the COM component belongs to a product, like the COM component of
Office, we could search for their .NET PIA from product owner and install
the PIA in your computer.

It sounds like this might be what I need. Will I be able to reference the
Office PIA, and still have my application deploy OK on a system that does
not have Office installed? What I do at the moment is disable those parts of
my application that rely on Excel if CreateObject fails to return a valid
reference. I can do this at runtime, but I'm concerned that if I explicitly
reference the COM object or the Interop Assembly that my application may not
run at all, when Office is unavailable.
3. If the COM component has no way to be retrieved, you may consider hook
up the events via IConnectionPoint interfaces. The KB article
http://support.microsoft.com/kb/811645/en-us gives an example. For more
information about COM events in .NET, please refer to
http://msdn2.microsoft.com/en-us/library/1hee64c7(VS.71).aspx

Thanks, I'll perhaps take a look at this and see if this might do the trick.
Please let me know if you have any other concerns, or need anything else.

Thanks for your response, it is most appreciated.
Cheers,
Phil.
 
J

Jialiang Ge [MSFT]

Hello Phil,

According to your reply, now I know that you are actually using late
binding, and trying to add event handlers for Excel.Application object.
Below, I will first provide two new workarounds for COM events in late
binding because the first two I provided in the last reply may not fit your
situation, then I will answer several additional questions you posted in
the last response.

The call of COM events in .NET are indeed different from the call of COM
methods/properties. We are able to access the COM methods/properties
without the reference of interop assemblies, but COM events cannot be
retrieved directly because .NET always requires a clearly defined event
source interface. For this specific problem, I find two workarounds for
your reference:

1. Since we decide to do late binding and cannot refer to the generated
COM-Interop wrapper (Office PIA), we need to copy the definition of the
interface into our COM client application, to simulate the job of
IConnectionPoint. The codeproject article
http://www.codeproject.com/csharp/zetalatebindingcomevents.asp shows a
complete explanation/example of it.
2. The second workaround is not to use late-binding. But in order to
support multiple office versions in target machine, we could reference the
type library of the earliest version of the Office application you intended
to Automate. For instance, if your application intends to support Office
2000 and above, we could add a reference to Office 2000 PIA. In this way,
we are using early binding and the event handlers can be easily added. For
more information, please refer to the KB article "Writing Automation
clients for multiple Office versions"
http://support.microsoft.com/kb/244167/

For your additional questions in the last reply:
Actually it returns 'Nothing' rather than an empty array, but you're
right, I don't see the events that I had hoped to see..
What I referred to is the method: 'GetEvents', rather than 'GetEvent'.
'GetEvents' returns all the events available to the COM object in the form
of an array. It returns an empty array if there are no events.
Actually I didn't know that. (About Office PIA)
A .NET COM interop assembly is necessary if a .NET class expects to access
COM events/methods/properties with early binding. Office Primary Interop
Assembly is such a thing that allows .NET clients automates Office COM
objects. Office 2003 PIA can be downloaded at
http://www.microsoft.com/downloads/details.aspx?familyid=3c9a983a-ac14-4125-
8ba0-d36d67e0f4ad&displaylang=en, Office 2007 PIA can be downloaded at
http://www.microsoft.com/downloads/details.aspx?familyid=59DAEBAA-BED4-4282-
A28C-B864D8BFA513&displaylang=en, and Office XP at:
http://www.microsoft.com/downloads/details.aspx?familyid=C41BD61E-3060-4F71-
A6B4-01FEBA508E52&displaylang=en
To add the reference to the PIAs in Visual Studio.NET, we should right
click the project->Add Reference->Turn to 'COM' tab->Find the object
library we need. For instance, for Excel automation, we could add Microsoft
Excel (version number) object library.

If you have any other question or need anything else, please feel free to
let me know.

Regards,
Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

=================================================
When responding to posts, please "Reply to Group" via your newsreader
so that others may learn and benefit from your issue.
=================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

Jialiang Ge [MSFT]

Hi Phil,

Would you mind letting me know the result of the suggestions? If you need
further assistance, feel free to let me know. I will be more than happy to
be of assistance.

Have a great day!

Sincerely,
Jialiang Ge ([email protected], remove 'online.')
Microsoft Online Community Support

=================================================
When responding to posts, please "Reply to Group" via your newsreader
so that others may learn and benefit from your issue.
=================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top