PC Review


Reply
Thread Tools Rate Thread

C# DLL with non .NET clients, getting ESP errors

 
 
dev
Guest
Posts: n/a
 
      6th Mar 2012
I have rewritten a COM DLL into C#, with a number of interface
functions, and a number of events that can be fired back to the
client(s). I can call it from a VB (6) client without problems.
However, when I try to use a C++ client (still visual studio 6) that
worked with the old DLL, any call to an interface function gets the
error "The value of ESP was not properly saved across a function
call."

A couple of example functions would be :
(C#)
int DialDigits([MarshalAs(UnmanagedType.BStr)]string
bsUserId,
[MarshalAs(UnmanagedType.BStr)]string szDigits);
int QueryStatusString([MarshalAs(UnmanagedType.BStr)] ref
string pbsStatus);
(C++)
m_pInterface->DialDigits(_bstr_t("1001").copy(),
_bstr_t("01234567890").copy());
BSTR bsError;
if ( m_pTapi->QueryStatusString( &bsError ) ==
S_OK ) ....
Both of these function calls get the same error.

The VB client doesn't seem to care whether the C# parameters are
marshalled or not, they just works, but I added the marshalling as
hinted by some other web site, but that didn't help in this C++ case.
Is there anything wrong with either my C#' interface definition, or
is
something special required in order to call a .NET COM dll from
unmanaged code ?

I can post the full interface if necessary, but it is a big lengthy.
I actually converted the IDL to C# by hand, but when it worked from
VB, I assumed I'd got it all right, but now I'm not so sure. Can
anyone help ?

I'm wondering if the issue is anything to do with the return type of
the
functions. In the old C++ DLL they were defined as STDMETHODIMP
(i.e. returning an HRESULT). What type should they therefore be in
C# ?

- Tim
 
Reply With Quote
 
 
 
 
dev
Guest
Posts: n/a
 
      7th Mar 2012
On Mar 6, 3:31*pm, Peter Duniho <(E-Mail Removed)> wrote:
> On Tue, 6 Mar 2012 07:18:24 -0800 (PST), dev wrote:
> > ........


Thanks for the quick reply. I don't really want to rewrite/recreate my
interface if I don't have to,
as its mostly done, and seems to be working well with a VB client. I
am still hoping that
it just needs a minor 'tweak' to make it work with a C++ client. I
will see if I can create
a simple example to post, as you suggested.

In the meantime, does anyone how to generate C# code from a tlb file
(using tlbimp or another
tool)? Some people have mentioned it, but so far all I've managed to
generate is another DLL.

- Tim
 
Reply With Quote
 
 
 
 
Arne Vajh°j
Guest
Posts: n/a
 
      8th Mar 2012
On 3/7/2012 5:16 AM, dev wrote:
> In the meantime, does anyone how to generate C# code from a tlb file
> (using tlbimp or another
> tool)? Some people have mentioned it, but so far all I've managed to
> generate is another DLL.


That is what you need.

:-)

The generated DLL is a .NET assembly which you just
add a ref to similar to any other .NET assembly.

And you can then you the types in the .NET assembly
in your C# code.

Arne


 
Reply With Quote
 
Arne Vajh°j
Guest
Posts: n/a
 
      8th Mar 2012
On 3/8/2012 5:08 PM, Arne Vajh°j wrote:
> On 3/7/2012 5:16 AM, dev wrote:
>> In the meantime, does anyone how to generate C# code from a tlb file
>> (using tlbimp or another
>> tool)? Some people have mentioned it, but so far all I've managed to
>> generate is another DLL.

>
> That is what you need.
>
> :-)
>
> The generated DLL is a .NET assembly which you just
> add a ref to similar to any other .NET assembly.
>
> And you can then you the types in the .NET assembly
> in your C# code.


Example.

VBS usage:

Set test = CreateObject("Test.CoTest")
WScript.Echo CStr(test.Add(123, 456))
WScript.Echo test.Concat("ABC", "XYZ")

C# usage with ref til DLL fra TLB import:

CoTest cotest = new CoTestClass();
ITest test = (ITest)cotest;
Console.WriteLine(test.Add(123, 456));
Console.WriteLine(test.Concat("ABC", "XYZ"));

C# usage without TLB import but instead using the C# 4.0 dynamic keyword:

dynamic test =
Activator.CreateInstance(Type.GetTypeFromProgID("Test.CoTest"));
Console.WriteLine(test.Add(123, 456));
Console.WriteLine(test.Concat("ABC", "XYZ"));

The examples are not completely equivalent as the C# via TLB import
does not go through IDispatch as the other two does.

Arne

 
Reply With Quote
 
Arne Vajh°j
Guest
Posts: n/a
 
      8th Mar 2012
On 3/6/2012 10:18 AM, dev wrote:
> I have rewritten a COM DLL into C#, with a number of interface
> functions, and a number of events that can be fired back to the
> client(s). I can call it from a VB (6) client without problems.
> However, when I try to use a C++ client (still visual studio 6) that
> worked with the old DLL, any call to an interface function gets the
> error "The value of ESP was not properly saved across a function
> call."
>
> A couple of example functions would be :
> (C#)
> int DialDigits([MarshalAs(UnmanagedType.BStr)]string
> bsUserId,
> [MarshalAs(UnmanagedType.BStr)]string szDigits);
> int QueryStatusString([MarshalAs(UnmanagedType.BStr)] ref
> string pbsStatus);
> (C++)
> m_pInterface->DialDigits(_bstr_t("1001").copy(),
> _bstr_t("01234567890").copy());
> BSTR bsError;
> if ( m_pTapi->QueryStatusString(&bsError ) ==
> S_OK ) ....
> Both of these function calls get the same error.
>
> The VB client doesn't seem to care whether the C# parameters are
> marshalled or not, they just works, but I added the marshalling as
> hinted by some other web site, but that didn't help in this C++ case.
> Is there anything wrong with either my C#' interface definition, or
> is
> something special required in order to call a .NET COM dll from
> unmanaged code ?
>
> I can post the full interface if necessary, but it is a big lengthy.
> I actually converted the IDL to C# by hand, but when it worked from
> VB, I assumed I'd got it all right, but now I'm not so sure. Can
> anyone help ?
>
> I'm wondering if the issue is anything to do with the return type of
> the
> functions. In the old C++ DLL they were defined as STDMETHODIMP
> (i.e. returning an HRESULT). What type should they therefore be in
> C# ?


There is way too much going on behind the scene for .NET-COM
interop for manual conversion to be a good conversion.

TLB import or using dynamic are the ways to go in C#.

(dynamic requires C# 4.0 or higher)

See examples in other post.

Arne

 
Reply With Quote
 
dev
Guest
Posts: n/a
 
      9th Mar 2012
On Mar 8, 10:17*pm, Arne Vajh°j <(E-Mail Removed)> wrote:
> On 3/6/2012 10:18 AM, dev wrote:
>
>
>
>
> > I have rewritten a COM DLL into C#, with a number of interface
> > functions, and a number of events that can be fired back to the
> > client(s). I can call it from a VB (6) client without problems.
> > However, when I try to use a C++ client (still visual studio 6) that
> > worked with the old DLL, any call to an interface function gets the
> > error "The value of ESP was not properly saved across a function
> > call."

>
> > A couple of example functions would be :
> > (C#)
> > * * * * *int DialDigits([MarshalAs(UnmanagedType.BStr)]string
> > bsUserId,
> > [MarshalAs(UnmanagedType.BStr)]string szDigits);
> > * * * * *int QueryStatusString([MarshalAs(UnmanagedType.BStr)] ref
> > string pbsStatus);
> > (C++)
> > * * * * * * * * *m_pInterface->DialDigits(_bstr_t("1001").copy(),
> > _bstr_t("01234567890").copy());
> > * * * * * * * * *BSTR bsError;
> > * * * * * * * * *if ( m_pTapi->QueryStatusString(&bsError ) ==
> > S_OK ) ....
> > Both of these function calls get the same error.

>
> > The VB client doesn't seem to care whether the C# parameters are
> > marshalled or not, they just works, but I added the marshalling as
> > hinted by some other web site, but that didn't help in this C++ case.
> > Is there anything wrong with either my C#' interface definition, or
> > is
> > something special required in order to call a .NET COM dll from
> > unmanaged code ?

>
> > I can post the full interface if necessary, but it is a big lengthy.
> > I actually converted the IDL to C# by hand, but when it worked from
> > VB, I assumed I'd got it all right, but now I'm not so sure. *Can
> > anyone help ?

>
> > I'm wondering if the issue is anything to do with the return type of
> > the
> > functions. In the old C++ DLL they were defined as STDMETHODIMP
> > (i.e. returning an HRESULT). What type should they therefore be in
> > C# ?

>
> There is way too much going on behind the scene for .NET-COM
> interop for manual conversion to be a good conversion.
>
> TLB import or using dynamic are the ways to go in C#.
>
> (dynamic requires C# 4.0 or higher)
>
> See examples in other post.
>
> Arne


Thanks for all the replies.

However, just to be clear, the C# here is the server, not a
replacement client.

How would a tlb import work in that situation ?

- Tim
 
Reply With Quote
 
Arne Vajh°j
Guest
Posts: n/a
 
      13th Mar 2012
On 3/9/2012 3:31 AM, dev wrote:
> On Mar 8, 10:17 pm, Arne Vajh°j<(E-Mail Removed)> wrote:
>> On 3/6/2012 10:18 AM, dev wrote:
>>> I have rewritten a COM DLL into C#, with a number of interface
>>> functions, and a number of events that can be fired back to the
>>> client(s). I can call it from a VB (6) client without problems.
>>> However, when I try to use a C++ client (still visual studio 6) that
>>> worked with the old DLL, any call to an interface function gets the
>>> error "The value of ESP was not properly saved across a function
>>> call."

>>
>>> A couple of example functions would be :
>>> (C#)
>>> int DialDigits([MarshalAs(UnmanagedType.BStr)]string
>>> bsUserId,
>>> [MarshalAs(UnmanagedType.BStr)]string szDigits);
>>> int QueryStatusString([MarshalAs(UnmanagedType.BStr)] ref
>>> string pbsStatus);
>>> (C++)
>>> m_pInterface->DialDigits(_bstr_t("1001").copy(),
>>> _bstr_t("01234567890").copy());
>>> BSTR bsError;
>>> if ( m_pTapi->QueryStatusString(&bsError ) ==
>>> S_OK ) ....
>>> Both of these function calls get the same error.

>>
>>> The VB client doesn't seem to care whether the C# parameters are
>>> marshalled or not, they just works, but I added the marshalling as
>>> hinted by some other web site, but that didn't help in this C++ case.
>>> Is there anything wrong with either my C#' interface definition, or
>>> is
>>> something special required in order to call a .NET COM dll from
>>> unmanaged code ?

>>
>>> I can post the full interface if necessary, but it is a big lengthy.
>>> I actually converted the IDL to C# by hand, but when it worked from
>>> VB, I assumed I'd got it all right, but now I'm not so sure. Can
>>> anyone help ?

>>
>>> I'm wondering if the issue is anything to do with the return type of
>>> the
>>> functions. In the old C++ DLL they were defined as STDMETHODIMP
>>> (i.e. returning an HRESULT). What type should they therefore be in
>>> C# ?

>>
>> There is way too much going on behind the scene for .NET-COM
>> interop for manual conversion to be a good conversion.
>>
>> TLB import or using dynamic are the ways to go in C#.
>>
>> (dynamic requires C# 4.0 or higher)
>>
>> See examples in other post.


> However, just to be clear, the C# here is the server, not a
> replacement client.
>
> How would a tlb import work in that situation ?


Ah.

That is a complete different scenario.

Sorry for misunderstanding completely.

For server you can either:
a) write both interfaces and classes from scratch and try to add
all the necessary attributes.
b) tlbimp and just write the classes from scratch implementing the
generated interfaces

Again I will consider solution #a for unsuitable for more complex
cases. But if you go this route then you can use tlbexp to generate
a new tlb and use a tool to compare the content of old and the new tlb.

But option #b should be the way to go.

You may find the book "COM and .NET Interoperability"
by Andrew Troelsen very useful.

Chapter 10 covers #a above and chapter 12 covers #b above.

The book used to be available for download.

Arne



 
Reply With Quote
 
Arne Vajh°j
Guest
Posts: n/a
 
      13th Mar 2012
On 3/12/2012 9:37 PM, Arne Vajh°j wrote:
> On 3/9/2012 3:31 AM, dev wrote:
>> On Mar 8, 10:17 pm, Arne Vajh°j<(E-Mail Removed)> wrote:
>>> On 3/6/2012 10:18 AM, dev wrote:
>>>> I have rewritten a COM DLL into C#, with a number of interface
>>>> functions, and a number of events that can be fired back to the
>>>> client(s). I can call it from a VB (6) client without problems.
>>>> However, when I try to use a C++ client (still visual studio 6) that
>>>> worked with the old DLL, any call to an interface function gets the
>>>> error "The value of ESP was not properly saved across a function
>>>> call."
>>>
>>>> A couple of example functions would be :
>>>> (C#)
>>>> int DialDigits([MarshalAs(UnmanagedType.BStr)]string
>>>> bsUserId,
>>>> [MarshalAs(UnmanagedType.BStr)]string szDigits);
>>>> int QueryStatusString([MarshalAs(UnmanagedType.BStr)] ref
>>>> string pbsStatus);
>>>> (C++)
>>>> m_pInterface->DialDigits(_bstr_t("1001").copy(),
>>>> _bstr_t("01234567890").copy());
>>>> BSTR bsError;
>>>> if ( m_pTapi->QueryStatusString(&bsError ) ==
>>>> S_OK ) ....
>>>> Both of these function calls get the same error.
>>>
>>>> The VB client doesn't seem to care whether the C# parameters are
>>>> marshalled or not, they just works, but I added the marshalling as
>>>> hinted by some other web site, but that didn't help in this C++ case.
>>>> Is there anything wrong with either my C#' interface definition, or
>>>> is
>>>> something special required in order to call a .NET COM dll from
>>>> unmanaged code ?
>>>
>>>> I can post the full interface if necessary, but it is a big lengthy.
>>>> I actually converted the IDL to C# by hand, but when it worked from
>>>> VB, I assumed I'd got it all right, but now I'm not so sure. Can
>>>> anyone help ?
>>>
>>>> I'm wondering if the issue is anything to do with the return type of
>>>> the
>>>> functions. In the old C++ DLL they were defined as STDMETHODIMP
>>>> (i.e. returning an HRESULT). What type should they therefore be in
>>>> C# ?
>>>
>>> There is way too much going on behind the scene for .NET-COM
>>> interop for manual conversion to be a good conversion.
>>>
>>> TLB import or using dynamic are the ways to go in C#.
>>>
>>> (dynamic requires C# 4.0 or higher)
>>>
>>> See examples in other post.

>
>> However, just to be clear, the C# here is the server, not a
>> replacement client.
>>
>> How would a tlb import work in that situation ?

>
> Ah.
>
> That is a complete different scenario.
>
> Sorry for misunderstanding completely.
>
> For server you can either:
> a) write both interfaces and classes from scratch and try to add
> all the necessary attributes.
> b) tlbimp and just write the classes from scratch implementing the
> generated interfaces
>
> Again I will consider solution #a for unsuitable for more complex
> cases. But if you go this route then you can use tlbexp to generate
> a new tlb and use a tool to compare the content of old and the new tlb.
>
> But option #b should be the way to go.
>
> You may find the book "COM and .NET Interoperability"
> by Andrew Troelsen very useful.
>
> Chapter 10 covers #a above and chapter 12 covers #b above.
>
> The book used to be available for download.


Hey. It still is.

http://www.theserverside.net/tt/arti...etInterop_Book

Arne

 
Reply With Quote
 
dev
Guest
Posts: n/a
 
      14th Mar 2012
Okay, the solution turned out to be fairly simple ...... after all
that.

It was that the #import needed to have a "no_namespace" option on it,
so that the definition matched that of the original COM server.

After a bit of fiddling with marshalling and types, I'm now calling my
COM
server functions correctly.

However, I'm still wasn't getting callbacks arriving, and I think I'll
post that
as a separate thread.

Many thanks to all those who responded.

- Tim
 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

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

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Restore Kernel32.dll dnsapi.dll powrprof.dll and wininet.dll Durward Rogers Windows XP Security 1 12th Dec 2009 11:27 PM
Re: The Logon User Interface DLL Msgina.dll failed to load. Contactyour system administrator to replace DLL or restore the original DLL. John John (MVP) Windows XP Help 0 9th May 2008 05:55 PM
mshtml.dll, shlwapi.dll, shdocvw.dll errors =?Utf-8?B?ZmFyc2hhZA==?= Windows XP Internet Explorer 3 18th Nov 2004 03:01 PM
FBALog errors - seclogon.dll, eventcls.dll, swpprv.dll =?Utf-8?B?R3JhYmhlciBHw7xudGVy?= Windows XP Embedded 3 6th Apr 2004 12:14 AM
Getting at old PST file (esp to Brian Tillman) Laurel Microsoft Outlook 2 24th Mar 2004 06:14 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 04:54 PM.