By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,142 Members | 1,831 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,142 IT Pros & Developers. It's quick & easy.

Dynamically create COM objects in C#

P: n/a
Ray
I want to dynamically load DLLs (created from VB) and instantiate a
class with a particular name, like "ProcessClass".

I am able to load the DLL and confirm there is a class by that name BUT
I can't seem to create it or call methods to this newly created
instance. I have the following code:

public class Script
{
[DllImport("oleaut32", CharSet=CharSet.Unicode)]
private extern static void LoadTypeLib(string dllFilePath, out
UCOMITypeLib typeLibrary);

UCOMITypeLib typeLibrary;
LoadTypeLib(dllName, out typeLibrary);

for (int i = 0; i < typeLibrary.GetTypeInfoCount(); i++)
{
typeLibrary.GetDocumentation(i, out typeName, out
typeDocumentation, out typeHelpContext, out typeHelpFile);
if (typeName == "ProcessClass")
{
UCOMITypeInfo typeInformation;
object classInstance;

typeLibrary.GetTypeInfo(i, out typeInformation);
typeInformation.CreateInstance(null, ref guidIUnknown, out
classInstance);

MethodInfo method = classType.GetMethod("DoSomething",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public
);
method.Invoke(classInstance, new object[0]);
}
}
}

Am I going down the wrong road? The class seems to be created without
exception, but the created instance doesn't seem to be bound properly
as I don't see any of the methods I'm looking for when I loop through!!

-Ray

Nov 17 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Ray,

First, you don't need to use interop and everything you are doing to
create an instance of your COM class. You can easily do this:

// Get the type of the COM object.
// I used Project as the dll name, because COM objects usually have a
two-part program id.
Type comType = Type.GetTypeFromProgID("Project.ProcessClass");

// Create an instance.
object instance = Activator.CreateObject(comType);

At that point, you have the instance of your object. You will need to
use reflection in order to make calls to the object.

In order to get around this, you should define an interface that
reflects the interface on the object you want to call. Since COM is an
interface-based system (even when VB is involved, which obfuscates that
fact), you can always get that interface and then have an early-bound
reference in your system.

The problem with this is that if you didn't originally define the
interface separately from the class in your project, then you will have to
use TLBIMP to get the definition, and not use the early bound types that are
defined for you.

Of course, if you only need this class in this dll, then why not just
set a reference to it directly?

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Ray" <ra********@email.com> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...
I want to dynamically load DLLs (created from VB) and instantiate a
class with a particular name, like "ProcessClass".

I am able to load the DLL and confirm there is a class by that name BUT
I can't seem to create it or call methods to this newly created
instance. I have the following code:

public class Script
{
[DllImport("oleaut32", CharSet=CharSet.Unicode)]
private extern static void LoadTypeLib(string dllFilePath, out
UCOMITypeLib typeLibrary);

UCOMITypeLib typeLibrary;
LoadTypeLib(dllName, out typeLibrary);

for (int i = 0; i < typeLibrary.GetTypeInfoCount(); i++)
{
typeLibrary.GetDocumentation(i, out typeName, out
typeDocumentation, out typeHelpContext, out typeHelpFile);
if (typeName == "ProcessClass")
{
UCOMITypeInfo typeInformation;
object classInstance;

typeLibrary.GetTypeInfo(i, out typeInformation);
typeInformation.CreateInstance(null, ref guidIUnknown, out
classInstance);

MethodInfo method = classType.GetMethod("DoSomething",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public
);
method.Invoke(classInstance, new object[0]);
}
}
}

Am I going down the wrong road? The class seems to be created without
exception, but the created instance doesn't seem to be bound properly
as I don't see any of the methods I'm looking for when I loop through!!

-Ray

Nov 17 '05 #2

P: n/a
Ray
Thanks Nicholas, I'm trying out your suggestion.

After I created the instance, I added the following:

MethodInfo method = comType.GetMethod("ProcessActive");
object result = method.Invoke(instance, new object[0]);

BUT GetMethod() returns null, and I know for sure the ProcessActive
exists. Do I need to create an ObjRef to get access to the actual
methods, because right now the only methods I'm getting are:
Method name: CreateObjRef
Method name: InitializeLifetimeService
Method name: GetLifetimeService
Method name: GetHashCode
Method name: Equals
Method name: ToString
Method name: GetType

-Ray

Nov 17 '05 #3

P: n/a
Ray,

The reason for this is because the type you get doesn't actually have
any members on it. The members you see are for the __ComObject type which
represents a COM object that is being used in interop. If you call the
InvokeMember method, passing the name of the member (as well as the correct
binding flags), it will work. Reflection knows enough to call through COM
(through the IDispatch implementation actually) to make the call to your
object.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com
"Ray" <ra********@email.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
Thanks Nicholas, I'm trying out your suggestion.

After I created the instance, I added the following:

MethodInfo method = comType.GetMethod("ProcessActive");
object result = method.Invoke(instance, new object[0]);

BUT GetMethod() returns null, and I know for sure the ProcessActive
exists. Do I need to create an ObjRef to get access to the actual
methods, because right now the only methods I'm getting are:
Method name: CreateObjRef
Method name: InitializeLifetimeService
Method name: GetLifetimeService
Method name: GetHashCode
Method name: Equals
Method name: ToString
Method name: GetType

-Ray

Nov 17 '05 #4

P: n/a
Ray
Thanks a lot for your help. I ended up with the following code for
those who are interested. As opposed to create the instance with the
ProgID, I had to create it with CLSID as I couldn't find an easy way to
retrieve the project name (in my case, not the same as the DLL name).

Type comType = Type.GetTypeFromCLSID(someClassID);
object comInstance = Activator.CreateInstance(comType);
comType.InvokeMember(someMethodName, BindingFlags.InvokeMethod |
BindingFlags.IgnoreReturn | BindingFlags.Public, null, comInstance, new
object[0]);

The code is now very simple.

Nov 17 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.