Frustrating COM Problem

  • Thread starter Thread starter oddball.bfi
  • Start date Start date
O

oddball.bfi

Hi there.

I need help retrieving the type of a COM object at run-time. All the
examples I've found assume you know the object type in advance - I
need some way to get a list of Interfaces a COM object implements.

It's driving me mad - help!
 
Hi there.

I need help retrieving the type of a COM object at run-time. All the
examples I've found assume you know the object type in advance - I
need some way to get a list of Interfaces a COM object implements.

It's driving me mad - help!

Now I'm afraid thats a tough one as this doesn't need to be documented. The
COM object *may* have this information in the typelibrary. However, the only
way to truely know is to call QueryInterface (cast using "as") on every
interface it could be. This is essentially what oleview.exe does - calls QI
on the object for each interface in the registry

--
Regards

Richard Blewett
DevelopMentor
http://www.dotnetconsult.co.uk/weblog2
 
Now I'm afraid thats a tough one as this doesn't need to be documented. The
COM object *may* have this information in the typelibrary. However, the only
way to truely know is to call QueryInterface (cast using "as") on every
interface it could be. This is essentially what oleview.exe does - calls QI
on the object for each interface in the registry

--
Regards

Richard Blewett
DevelopMentorhttp://www.dotnetconsult.co.uk/weblog2

Oh dear god - that's hardly something I can do every time I run the
software...

I'm looking for any solutions that let me dodge this - anything at
all. Is that how the Object Browser gets it's info too?
 
Oh dear god - that's hardly something I can do every time I run the
software...

I'm looking for any solutions that let me dodge this - anything at
all. Is that how the Object Browser gets it's info too?

Well the issue is how accurate does this have to be?

You could use the typelib (which is what I'm guessing Type.GetInterfaces
will give you - although I might be wrong). Or you could run QI against the
COM object once and store the results somewhere. Do you care about a subset
of interfaces or do you really care about all of them (such as IMarshal,
IMarshal2, IPersistPropertyBag, etc)?

--
Regards

Richard Blewett
DevelopMentor
http://www.dotnetconsult.co.uk/weblog2
 
Well the issue is how accurate does this have to be?

You could use the typelib (which is what I'm guessing Type.GetInterfaces
will give you - although I might be wrong). Or you could run QI against the
COM object once and store the results somewhere. Do you care about a subset
of interfaces or do you really care about all of them (such as IMarshal,
IMarshal2, IPersistPropertyBag, etc)?

--
Regards

Richard Blewett
DevelopMentorhttp://www.dotnetconsult.co.uk/weblog2

I basicaly need to identify the object type so I can send it to a
handler. I only care about one or two specific interfaces, just
enough to pass the object to the right handler which runs a specific
cast and does it's jiggery pokery.

Type at = Type.GetType(wca.AddType); // Add type is a string name of a
COM interface.

Why is this returning NULL!!!!

Join me in the pub this evening and I'll tell you all about third-
party libraries that just throw a bunch of untyped objects at you and
expect you to deal.
 
I basicaly need to identify the object type so I can send it to a
handler. I only care about one or two specific interfaces, just
enough to pass the object to the right handler which runs a specific
cast and does it's jiggery pokery.

Type at = Type.GetType(wca.AddType); // Add type is a string name of a
COM interface.

Why is this returning NULL!!!!

Join me in the pub this evening and I'll tell you all about third-
party libraries that just throw a bunch of untyped objects at you and
expect you to deal.

OK, so with the way you have called this method it is expecting the
interface to live within your application (assembly). If you want this to
work you will have to add the assembly name on to the string. Suppose the
assembly housing the Runtime Callable Wrapper (I assume you have already
created an RCW) is called MyCOMStuff.dll and has been signed with a public
key token, then you need to pass in something like

wca.AddType, MyCOMStuff, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=<token used for signing>

This will get you the type object for the interface. The question is, is
this really what you want? Aren't you trying to find out if a specific
object implements an interface or have I misunderstood?

Regards

Richard Blewett
DevelopMentor
http://www.dotnetconsult.co.uk/weblog2
 
I basicaly need to identify the object type so I can send it to a
handler. I only care about one or two specific interfaces, just
enough to pass the object to the right handler which runs a specific
cast and does it's jiggery pokery.

Type at = Type.GetType(wca.AddType); // Add type is a string name of a
COM interface.

Why is this returning NULL!!!!


I don't know much about what your trying to do....but GetType() accepts a
string parameter, so maybe it should be:

Type at = Type.GetType("wca.AddType");
 
Wait, according to your comment it is a string argument....sorry.
 
I basicaly need to identify the object type so I can send it to a
handler. I only care about one or two specific interfaces, just
enough to pass the object to the right handler which runs a specific
cast and does it's jiggery pokery.

Type at = Type.GetType(wca.AddType); // Add type is a string name of a
COM interface.

Why is this returning NULL!!!!

Join me in the pub this evening and I'll tell you all about third-
party libraries that just throw a bunch of untyped objects at you and
expect you to deal.


What exactly do you mean with "string name of a COM interface" here?

Type at = Type.GetType(wca.AddType); // Add type is a string name of a COM
interface.

what does wca.AddType contain?

Interfaces are identified using UUID's, so you need to specify the UUID of
the interface (the IID) you are looking for in a call to QI.
Herewith a small sample calling a method on a native COM object using late
binding.


string progId = "SimpleCom.Bird";
Type t = Type.GetTypeFromProgID(progId);
if (t == null)
{
throw new Exception("Invalid ProgID.");
}
Console.WriteLine("GUID for ProgID RemServer.Server is {0}.",
t.GUID);
object o = Activator.CreateInstance(t); // create an instance
of this server
IntPtr pUnkn = Marshal.GetIUnknownForObject(o); // Get the
IUnknow pointer
Guid IID = new Guid("0938B479-ED9A-4997-B780-85AF420E01FF"); //
This is the Interface I need
IntPtr ppv;
int hResult = Marshal.QueryInterface(pUnkn, ref IID, out ppv);
// Does above Interface exists?
if(hResult < 0)
{ throw ... }
else
{
// success, use interface
object bird = Marshal.GetObjectForIUnknown(ppv);
//late bound call
bird .GetType().InvokeMember("Fly",
BindingFlags.InvokeMethod, null, bird , new Object[] {"To Somewhere"});

...

Willy.
 
I basicaly need to identify the object type so I can send it to a
handler. I only care about one or two specific interfaces, just
enough to pass the object to the right handler which runs a specific
cast and does it's jiggery pokery.
Type at = Type.GetType(wca.AddType); // Add type is a string name of a
COM interface.
Why is this returning NULL!!!!
Join me in the pub this evening and I'll tell you all about third-
party libraries that just throw a bunch of untyped objects at you and
expect you to deal.

What exactly do you mean with "string name of a COM interface" here?

Type at = Type.GetType(wca.AddType); // Add type is a string name of a COM
interface.

what does wca.AddType contain?

Interfaces are identified using UUID's, so you need to specify the UUID of
the interface (the IID) you are looking for in a call to QI.
Herewith a small sample calling a method on a native COM object using late
binding.

string progId = "SimpleCom.Bird";
Type t = Type.GetTypeFromProgID(progId);
if (t == null)
{
throw new Exception("Invalid ProgID.");
}
Console.WriteLine("GUID for ProgID RemServer.Server is {0}.",
t.GUID);
object o = Activator.CreateInstance(t); // create an instance
of this server
IntPtr pUnkn = Marshal.GetIUnknownForObject(o); // Get the
IUnknow pointer
Guid IID = new Guid("0938B479-ED9A-4997-B780-85AF420E01FF"); //
This is the Interface I need
IntPtr ppv;
int hResult = Marshal.QueryInterface(pUnkn, ref IID, out ppv);
// Does above Interface exists?
if(hResult < 0)
{ throw ... }
else
{
// success, use interface
object bird = Marshal.GetObjectForIUnknown(ppv);
//late bound call
bird .GetType().InvokeMember("Fly",
BindingFlags.InvokeMethod, null, bird , new Object[] {"To Somewhere"});

...

Willy.

It's the AQN of the Type in the Interop assembly.
 
Oddball said:
Hi there.
I need help retrieving the type of a COM object at run-time. All
the
examples I've found assume you know the object type in advance -
I
need some way to get a list of Interfaces a COM object
implements.
It's driving me mad - help!
Now I'm afraid thats a tough one as this doesn't need to be
documented.
The
COM object *may* have this information in the typelibrary. However,
the
only
way to truely know is to call QueryInterface (cast using "as") on
every
interface it could be. This is essentially what oleview.exe does -
calls
QI
on the object for each interface in the registry
Richard Blewett
DevelopMentorhttp://www.dotnetconsult.co.uk/weblog2
Oh dear god - that's hardly something I can do every time I run the
software...
I'm looking for any solutions that let me dodge this - anything at
all. Is that how the Object Browser gets it's info too?
Well the issue is how accurate does this have to be?
You could use the typelib (which is what I'm guessing
Type.GetInterfaces
will give you - although I might be wrong). Or you could run QI
against
the
COM object once and store the results somewhere. Do you care about a
subset
of interfaces or do you really care about all of them (such as
IMarshal,
IMarshal2, IPersistPropertyBag, etc)?
Richard Blewett
DevelopMentorhttp://www.dotnetconsult.co.uk/weblog2
I basicaly need to identify the object type so I can send it to a
handler. I only care about one or two specific interfaces, just
enough to pass the object to the right handler which runs a specific
cast and does it's jiggery pokery.
Type at = Type.GetType(wca.AddType); // Add type is a string name of a
COM interface.
Why is this returning NULL!!!!
Join me in the pub this evening and I'll tell you all about third-
party libraries that just throw a bunch of untyped objects at you and
expect you to deal.

What exactly do you mean with "string name of a COM interface" here?

Type at = Type.GetType(wca.AddType); // Add type is a string name of a
COM
interface.

what does wca.AddType contain?

Interfaces are identified using UUID's, so you need to specify the UUID
of
the interface (the IID) you are looking for in a call to QI.
Herewith a small sample calling a method on a native COM object using
late
binding.

string progId = "SimpleCom.Bird";
Type t = Type.GetTypeFromProgID(progId);
if (t == null)
{
throw new Exception("Invalid ProgID.");
}
Console.WriteLine("GUID for ProgID RemServer.Server is {0}.",
t.GUID);
object o = Activator.CreateInstance(t); // create an
instance
of this server
IntPtr pUnkn = Marshal.GetIUnknownForObject(o); // Get the
IUnknow pointer
Guid IID = new Guid("0938B479-ED9A-4997-B780-85AF420E01FF");
//
This is the Interface I need
IntPtr ppv;
int hResult = Marshal.QueryInterface(pUnkn, ref IID, out
ppv);
// Does above Interface exists?
if(hResult < 0)
{ throw ... }
else
{
// success, use interface
object bird = Marshal.GetObjectForIUnknown(ppv);
//late bound call
bird .GetType().InvokeMember("Fly",
BindingFlags.InvokeMethod, null, bird , new Object[] {"To Somewhere"});

...

Willy.

It's the AQN of the Type in the Interop assembly.



If you have imported the IA, then you can simply cast the interface you got
from an instantiation call to any other interface implemented by the
component.

...
SomeNamespace.Animal animal = new SomeNamespace.AnimalClass();
// cast animal to wanted ITF, this performs a QueryInterface
under the covers
SomeNamespace.IBird bird = animal as SomeNamespace.IBird;
if(bird != null)
bird.Fly();
else
{
SomeNamespace.IDog dog as SomeNamespace.IDog;
if(dog != null)
dog.Bark();
...

Willy.



Willy.
 

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

Similar Threads


Back
Top