CreateDelegate error

M

Max

I'm using late binding to automate to Outlook and I'm getting an
ArgumentException when I create a delegate. The arguments I pass seem valid.
This is my code:

Code:
Type oType = Type.GetTypeFromProgID("Outlook.Application");
oApp = Activator.CreateInstance(oType);

oInspectors = oApp.GetType().GetProperty("Inspectors").GetValue(oApp, null);

e_NewInspector = oInspectors.GetType().GetEvent("NewInspector");
d_NewEventDelegate = Delegate.CreateDelegate(e_NewInspector.EventHandlerType,
this, "Inspectors_NewInspector");

The class that is supposed to handle the event is defined as follows:

Code:
private void Inspectors_NewInspector(object insp){ .... }

What am I doing wrong?
 
N

Nicholas Paldino [.NET/C# MVP]

Max,

When you look at the type for the event handler for NewInspector in
reflector, what is the signature.

Also, you don't really specify the details of the ArgumentException.
Those would be helpful.

I've noticed you are doing a lot of late binding to Outlook. Is there a
reason you aren't using the Primary Interop Assemblies, or even using VB to
handle the late binding (it's MUCH easier in VB).

Hope this helps.
 
M

Max

Hi Nicholas,

Thank you for your help. The exception I'm getting for CreateDelegate says:

System.ArgumentException: Error binding to target method.
at System.Delegate.InternalCreate(Object target, String method, Boolean ignoreCase)
at System.Delegate.CreateDelegate(Type type, Object target, String method)

Obviously it means "this" is not the way to go but "Inspectors_NewInspector" is defined in the
class that calls all the late binding code.


The debugger says that:
e_NewInspector has EventHandlerType with BaseType as {"System.MulticastDelegate"}


While the signature with early binding for the handler is like this:

InspectorsEvents_NewInspectorEventHandler(void(Microsoft.Office.Interop.Outlook.Inspector)target)
OR
InspectorsEvents_NewInspectorEventHandler(object param, System.UIntPtr param)

The software I'm working on runs on a server which is on 24/7 and to which units in the field
equipped with modems connect to and upload their data. The data is stored in a database and
displayed to the user. I need an option that will generate a service call in the sense that it
will launch either of: MS Outlook 2000, 2002, 2003 or Outlook Express and create an email and fill
the body with some HTML text (I use HTML for indentation purposes). I could use the 2003 PIA but
that won't cover MS Outlook 2000 hence I use late binding. I could use VB but I don't have too
much experiece with it so I work in C# :)


Nicholas Paldino said:
Max,

When you look at the type for the event handler for NewInspector in
reflector, what is the signature.

Also, you don't really specify the details of the ArgumentException.
Those would be helpful.

I've noticed you are doing a lot of late binding to Outlook. Is there a
reason you aren't using the Primary Interop Assemblies, or even using VB to
handle the late binding (it's MUCH easier in VB).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Max said:
I'm using late binding to automate to Outlook and I'm getting an
ArgumentException when I create a delegate. The arguments I pass seem
valid.
This is my code:

Code:
Type oType = Type.GetTypeFromProgID("Outlook.Application");
oApp = Activator.CreateInstance(oType);

oInspectors = oApp.GetType().GetProperty("Inspectors").GetValue(oApp,
null);

e_NewInspector = oInspectors.GetType().GetEvent("NewInspector");
d_NewEventDelegate =
Delegate.CreateDelegate(e_NewInspector.EventHandlerType, this,
"Inspectors_NewInspector");

The class that is supposed to handle the event is defined as follows:

Code:
private void Inspectors_NewInspector(object insp){ .... }

What am I doing wrong?
 
W

Willy Denoyette [MVP]

I could be wrong, but It looks like you are running this on a system that
has the PIA's installed in the GAC, where do you think reflection and the
debugger gets this "Microsoft.Office.Interop.Outlook.Inspector" from?
Watch the loaded assemblies in the debugger, bet you'll see that
"Microsoft.Office.Interop.Outlook.dll" is loaded from the GAC, your program
will probably fail when run on a system that won't have the outlook PIA
installed.

Willy.

Max said:
Hi Nicholas,

Thank you for your help. The exception I'm getting for CreateDelegate
says:

System.ArgumentException: Error binding to target method.
at System.Delegate.InternalCreate(Object target, String method, Boolean
ignoreCase)
at System.Delegate.CreateDelegate(Type type, Object target, String
method)

Obviously it means "this" is not the way to go but
"Inspectors_NewInspector" is defined in the
class that calls all the late binding code.


The debugger says that:
e_NewInspector has EventHandlerType with BaseType as
{"System.MulticastDelegate"}


While the signature with early binding for the handler is like this:

InspectorsEvents_NewInspectorEventHandler(void(Microsoft.Office.Interop.Outlook.Inspector)target)
OR
InspectorsEvents_NewInspectorEventHandler(object param, System.UIntPtr
param)

The software I'm working on runs on a server which is on 24/7 and to which
units in the field
equipped with modems connect to and upload their data. The data is stored
in a database and
displayed to the user. I need an option that will generate a service call
in the sense that it
will launch either of: MS Outlook 2000, 2002, 2003 or Outlook Express and
create an email and fill
the body with some HTML text (I use HTML for indentation purposes). I
could use the 2003 PIA but
that won't cover MS Outlook 2000 hence I use late binding. I could use VB
but I don't have too
much experiece with it so I work in C# :)


Nicholas Paldino said:
Max,

When you look at the type for the event handler for NewInspector in
reflector, what is the signature.

Also, you don't really specify the details of the ArgumentException.
Those would be helpful.

I've noticed you are doing a lot of late binding to Outlook. Is there
a reason you aren't using the Primary Interop Assemblies, or even using
VB to handle the late binding (it's MUCH easier in VB).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Max said:
I'm using late binding to automate to Outlook and I'm getting an
ArgumentException when I create a delegate. The arguments I pass seem
valid.
This is my code:

Code:
Type oType = Type.GetTypeFromProgID("Outlook.Application");
oApp = Activator.CreateInstance(oType);

oInspectors = oApp.GetType().GetProperty("Inspectors").GetValue(oApp,
null);

e_NewInspector = oInspectors.GetType().GetEvent("NewInspector");
d_NewEventDelegate =
Delegate.CreateDelegate(e_NewInspector.EventHandlerType, this,
"Inspectors_NewInspector");

The class that is supposed to handle the event is defined as follows:

Code:
private void Inspectors_NewInspector(object insp){ .... }

What am I doing wrong?
 
M

Max

That is correct. I am working on two solutions at the same time: one using early binding
and one using late binding. I installed the PIA's in the GAC and the setup project ships
with the dlls needed by the application for early binding. Am I doing this wrong?



Willy Denoyette said:
I could be wrong, but It looks like you are running this on a system that
has the PIA's installed in the GAC, where do you think reflection and the
debugger gets this "Microsoft.Office.Interop.Outlook.Inspector" from?
Watch the loaded assemblies in the debugger, bet you'll see that
"Microsoft.Office.Interop.Outlook.dll" is loaded from the GAC, your program
will probably fail when run on a system that won't have the outlook PIA
installed.

Willy.

Max said:
Hi Nicholas,

Thank you for your help. The exception I'm getting for CreateDelegate
says:

System.ArgumentException: Error binding to target method.
at System.Delegate.InternalCreate(Object target, String method, Boolean
ignoreCase)
at System.Delegate.CreateDelegate(Type type, Object target, String
method)

Obviously it means "this" is not the way to go but
"Inspectors_NewInspector" is defined in the
class that calls all the late binding code.


The debugger says that:
e_NewInspector has EventHandlerType with BaseType as
{"System.MulticastDelegate"}


While the signature with early binding for the handler is like this:

InspectorsEvents_NewInspectorEventHandler(void(Microsoft.Office.Interop.Outlook.Inspector)target)
OR
InspectorsEvents_NewInspectorEventHandler(object param, System.UIntPtr
param)

The software I'm working on runs on a server which is on 24/7 and to which
units in the field
equipped with modems connect to and upload their data. The data is stored
in a database and
displayed to the user. I need an option that will generate a service call
in the sense that it
will launch either of: MS Outlook 2000, 2002, 2003 or Outlook Express and
create an email and fill
the body with some HTML text (I use HTML for indentation purposes). I
could use the 2003 PIA but
that won't cover MS Outlook 2000 hence I use late binding. I could use VB
but I don't have too
much experiece with it so I work in C# :)


Nicholas Paldino said:
Max,

When you look at the type for the event handler for NewInspector in
reflector, what is the signature.

Also, you don't really specify the details of the ArgumentException.
Those would be helpful.

I've noticed you are doing a lot of late binding to Outlook. Is there
a reason you aren't using the Primary Interop Assemblies, or even using
VB to handle the late binding (it's MUCH easier in VB).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I'm using late binding to automate to Outlook and I'm getting an
ArgumentException when I create a delegate. The arguments I pass seem
valid.
This is my code:

Code:
Type oType = Type.GetTypeFromProgID("Outlook.Application");
oApp = Activator.CreateInstance(oType);

oInspectors = oApp.GetType().GetProperty("Inspectors").GetValue(oApp,
null);

e_NewInspector = oInspectors.GetType().GetEvent("NewInspector");
d_NewEventDelegate =
Delegate.CreateDelegate(e_NewInspector.EventHandlerType, this,
"Inspectors_NewInspector");

The class that is supposed to handle the event is defined as follows:

Code:
private void Inspectors_NewInspector(object insp){ .... }

What am I doing wrong?
 
W

Willy Denoyette [MVP]

As I said, you think you are using "late binding", but you are using
reflection to retrieve the CLR type information in order to bind
dynamically, this is not exactly the same thing as using COM late binding.
That means that this...
Type.GetProperty("Inspectors").GetValue(oApp, null);
uses the IA metadata to get the Property "Inpectors", it's obvious that this
will fail if there is no IA.
That means that you rely on the correct IA to be available when deploying,
right?. Question is who's going to install this IA, and who is going to
install a new version of the IA when the enduser install a new version of
outlook?

As I said before, what you need is real COM late binding (using the Outlook
Typelib), and this is realy hard to do in .NET, and it makes little sense as
you have better options.
What you can do for instance is build an assembly per outlook version you
want to target (using early binding), after you've checked the outlook
version installed you dynamically load the versioned assembly, all you need
to do is distribute the IA's and the versioned assemblies with your
application.
Another option is to build a simple SMTP mail client, so you don't need to
rely on outlook automation at all, I guess you don't need that fancy stuff
anyway, so it should trivial to do.


Willy.

Max said:
That is correct. I am working on two solutions at the same time: one using
early binding
and one using late binding. I installed the PIA's in the GAC and the setup
project ships
with the dlls needed by the application for early binding. Am I doing this
wrong?



Willy Denoyette said:
I could be wrong, but It looks like you are running this on a system that
has the PIA's installed in the GAC, where do you think reflection and the
debugger gets this "Microsoft.Office.Interop.Outlook.Inspector" from?
Watch the loaded assemblies in the debugger, bet you'll see that
"Microsoft.Office.Interop.Outlook.dll" is loaded from the GAC, your
program will probably fail when run on a system that won't have the
outlook PIA installed.

Willy.

Max said:
Hi Nicholas,

Thank you for your help. The exception I'm getting for CreateDelegate
says:

System.ArgumentException: Error binding to target method.
at System.Delegate.InternalCreate(Object target, String method,
Boolean ignoreCase)
at System.Delegate.CreateDelegate(Type type, Object target, String
method)

Obviously it means "this" is not the way to go but
"Inspectors_NewInspector" is defined in the
class that calls all the late binding code.


The debugger says that:
e_NewInspector has EventHandlerType with BaseType as
{"System.MulticastDelegate"}


While the signature with early binding for the handler is like this:

InspectorsEvents_NewInspectorEventHandler(void(Microsoft.Office.Interop.Outlook.Inspector)target)
OR
InspectorsEvents_NewInspectorEventHandler(object param, System.UIntPtr
param)

The software I'm working on runs on a server which is on 24/7 and to
which units in the field
equipped with modems connect to and upload their data. The data is
stored in a database and
displayed to the user. I need an option that will generate a service
call in the sense that it
will launch either of: MS Outlook 2000, 2002, 2003 or Outlook Express
and create an email and fill
the body with some HTML text (I use HTML for indentation purposes). I
could use the 2003 PIA but
that won't cover MS Outlook 2000 hence I use late binding. I could use
VB but I don't have too
much experiece with it so I work in C# :)


in message Max,

When you look at the type for the event handler for NewInspector in
reflector, what is the signature.

Also, you don't really specify the details of the ArgumentException.
Those would be helpful.

I've noticed you are doing a lot of late binding to Outlook. Is
there a reason you aren't using the Primary Interop Assemblies, or even
using VB to handle the late binding (it's MUCH easier in VB).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I'm using late binding to automate to Outlook and I'm getting an
ArgumentException when I create a delegate. The arguments I pass seem
valid.
This is my code:

Code:
Type oType = Type.GetTypeFromProgID("Outlook.Application");
oApp = Activator.CreateInstance(oType);

oInspectors = oApp.GetType().GetProperty("Inspectors").GetValue(oApp,
null);

e_NewInspector = oInspectors.GetType().GetEvent("NewInspector");
d_NewEventDelegate =
Delegate.CreateDelegate(e_NewInspector.EventHandlerType, this,
"Inspectors_NewInspector");

The class that is supposed to handle the event is defined as follows:

Code:
private void Inspectors_NewInspector(object insp){ .... }

What am I doing wrong?
 
M

Max

What you can do for instance is build an assembly per outlook version you
want to target (using early binding), after you've checked the outlook
version installed you dynamically load the versioned assembly, all you need
to do is distribute the IA's and the versioned assemblies with your
application.

I'm kind of new to this, as you might have realized already....

So you are saying to use the tlbimp.exe utility to create my own IAs for MS Outlook 2000, 2002, 2003
then make 3 separate dlls each one using early binding to do the work for each of the
MS Outlook versions 2000, 2002, 2003 resp. Then at run time based on the user selection to load the
correct assembly and call the right functions inside.... right?

Thanks,
Max
 
W

Willy Denoyette [MVP]

Max said:
I'm kind of new to this, as you might have realized already....

So you are saying to use the tlbimp.exe utility to create my own IAs for
MS Outlook 2000, 2002, 2003
then make 3 separate dlls each one using early binding to do the work for
each of the
MS Outlook versions 2000, 2002, 2003 resp. Then at run time based on the
user selection to load the
correct assembly and call the right functions inside.... right?

Thanks,
Max

No, it's not up to the user to decide which assembly to load, it's your
program code that checks the version by creating an instance of the outlook
server, something like this...

string progId = "Outlook.Application";
Type type1 = Type.GetTypeFromProgID(progId);
object outl = Activator.CreateInstance(type1);
// Get installed version of outlook, note that this call might load
the IA from the GAC when present.
object version = outl.GetType().InvokeMember("Version",
BindingFlags.GetProperty , null, outl, null);
// verions should hold a string that looks like "10.0.xxx or
11.0.0.xxxx etc..
// depending on the version you should load your versioned assembly

if(version = 11)
Assembly.Load("V11Assembly, Version=..., Culture=...")
if(version= 10)
...


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


Top