baffled by exception

G

Guest

Hello.
Does anybody know if there is a difference between the way C# calls a COM
object, and the way C++ calls a COM object? And is there anyway to make the
latter emulate the former?

I have a COM object which seemingly can't be instantiated using C++, but can
using C# and VB, and it's driving me insane - I can't work out what's wrong
with it.
It just seems to throw an exception, citing 'User Breakpoint' as the cause
of the exception when any C++ code tried to instantiate it.
If I click 'continue' to the exception when it's in debug mode, it rethrows
it as:
System.Runtime.InteropServices.COMException (0xC0000096): Exception from
HRESULT: 0xC0000096.

But it still throws up the message box when the try..catch is round it!
This COM object, I fully own and the dongle to it is plugged in. Like I say,
I can instantiate this COM object in other languages and I can instantiate
other COM objects using these methods in C++.

Is it possible they could have not wanted you to use it from C++, and can
tell?
Any ideas?


Cheers!
 
N

Nicholas Paldino [.NET/C# MVP]

Bonj,

This seems highly unlikely to me, as the mechanism in .NET ultimately
uses the same mechanism that C++ uses. Can you show how you are doing it in
..NET and how you are doing it in C++? Perhaps you are not setting up the
environment or the apartment correctly, and this could be the source of your
problems.

Hope this helps.
 
N

Nicholas Paldino [.NET/C# MVP]

Bonj,

This seems highly unlikely to me, as the mechanism in .NET ultimately
uses the same mechanism that C++ uses. Can you show how you are doing it in
..NET and how you are doing it in C++? Perhaps you are not setting up the
environment or the apartment correctly, and this could be the source of your
problems.

Hope this helps.
 
R

Richard Blewett [DevelopMentor]

An apartment type mismatch is only going to be a problem if the COM marshalling code (proxy/stub) is not installed properly. This error is a COM error relating to a privileged instruction attempting to be used. It is often in relation to the proxy/stub dll (that has the interface marshalling code in it) being out of step with the definition of the interface the COM object has implemented.

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<[email protected]>

Bonj,

This seems highly unlikely to me, as the mechanism in .NET ultimately
uses the same mechanism that C++ uses. Can you show how you are doing it in
.NET and how you are doing it in C++? Perhaps you are not setting up the
environment or the apartment correctly, and this could be the source of your
problems.

Hope this helps.
 
G

Guest

Can you show how you are doing it in
..NET and how you are doing it in C++?
(The library is called MyObjX and the object is called MyObj):

in C++:

#include "stdafx.h"

#using <mscorlib.dll>

using namespace System;
using namespace Interop::MyObjX;
using namespace System::Runtime::InteropServices;

[STAThread]
int _tmain()
{
MyObjClass* emb = __gc new MyObjClass();
return 0;
}


//in unmanaged c++ (I first added the myobj.IDL file with the contents of
its type library in COM / object viewer, and then compiled it to produce
myobj_i.c and myobj_h.h

#include <tchar.h>
#include <objbase.h>
#include <comdef.h>
#include "myobj_h.h"

void GetPrediction()
{
HRESULT hr = CoInitialize(NULL);
_MyObj* ip;
try
{
hr = CoCreateInstance(CLSID_MyObj, NULL, CLSCTX_INPROC_SERVER, IID__MyObj,
(void**)&ip);
}
catch(_com_error e)
{
const _TCHAR* s = e.ErrorMessage();
}
CoUninitialize();
}


// in C# (which works):

using System;
using MyObjX;

namespace UseEmbCsharp
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static int Main(string[] args)
{
MyObjX.MyObjClass p = new MyObjClass();
return 0;
}
}
}
This seems highly unlikely to me, as the mechanism in .NET ultimately
uses the same mechanism that C++ uses.

That's what I thought. This is why it baffles me.
Perhaps you are not setting up the
environment or the apartment correctly, and this could be the source of your
problems.

I can't see what differences there could be - if you can think of any,
please let me know! I've added the [STAThread] attribute to the main of the
MC++ project just like the C# one, and it still doesn't work. I don't know
how to set this for UMC++ - but I think it's more likely to be a security
thing than a threading thing - as the exception that is thrown completely
ignores try..catch handlers, and the COM object is protected with a dongle.
But it is installed completely correctly and legally, and the dongle is
plugged in, and as I say, it works from all languages but ANY breed of
C++.... it's completely weird......
 
S

Sigurd Stenersen

Bonj said:
//in unmanaged c++ (I first added the myobj.IDL file with the
contents of its type library in COM / object viewer, and then
compiled it to produce myobj_i.c and myobj_h.h

Try using #import and smart pointers instead.
 
G

Guest

This sounds more like it...

Are you able to provide any more information on how this problem might have
manifested itself in this scenario, and how I might go about curing it?
 
R

Richard Blewett [DevelopMentor]

If you reversed engineered the typelib, you may have lost some of the marshalling information. Some IDL constructs don't make it into the typelib ([size_is] for example).You may be working from a different set of marshalling instructions than the COM object.

As Sigurd suggested, if they have't provided you with a header file use #import to import the typelib.

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<[email protected]>

This sounds more like it...

Are you able to provide any more information on how this problem might have
manifested itself in this scenario, and how I might go about curing it?
 
G

Guest

mmmm. I might try that again, but I definitely did that and it didn't work.

But you think that by getting the MIDL out of 'OLE/COM object viewer' from
the 'Type libraries' section and copying and pasting it into an .idl file and
then compiling that, I might have lost some information, that I possibly
wouldn't have lost by using smart pointers?

Is copying and pasting from OLE/COM object viewer's Type Libraries section
the best way to do it if I am going to go down the CoCreateInstance path?


Anyhow thanks for your help on this
 
G

Guest

nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<[email protected]>

Is the above a link to information you think I might benefit from looking at?
If so, could you possibly copy and paste the pertinent bits into a message
and post back, because our firewall doesn't allow downloading over port 119
(nntp), we're only allowed to look at http.





Cheers
 
W

Willy Denoyette [MVP]

And both C++ and MC++ exceptions thrown are the same?
Note that 0XC0000096 isn't a COM exception but a Win32 error code thrown as
a result of a CPU interupt - while trying to execute a privileged
instruction in user mode.
This is weird, and point's to the COM server code itself.

Willy.
 
G

Guest

That doesn't surprise me... but how would it be possible to write a COM
component that works successfully from C# and VB, but doesn't work from C++ ??
 
O

Oleg Starodumov

Is it possible to reproduce the problem in a simplest possible application
that only instantiates and uses this COM object and does nothing more?
(Preferrably in unmanaged C++)

Regards,
Oleg
 
G

Guest

Not really, because it isn't a standard one - it's a third party custom
software, and is protected with a dongle. I have emailed the company that
produces it to ask them but whether they'll know or be able to tell me I
don't know. However I have got it fully legally installed and the dongle is
installed on my pc. The strangest thing is it works from VB.NET, VB6 and C#,
just not from any brand of C++.

The code I have been using is this:

#import "c:\program files\emblem modeller 3\MyObjx.dll"
#include <tchar.h>

int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
MyObjX::_MyObjPtr model;
HRESULT hr = model.CreateInstance(__uuidof(MyObjX::MyObj));
if(hr == S_OK) MessageBox(NULL, _T("EMB Model successfully created"),
_T("COM test"), MB_OK); //it never is.
CoUninitialize();
}
 
S

Sigurd Stenersen

Bonj said:
#import "c:\program files\emblem modeller 3\MyObjx.dll"
MyObjX::_MyObjPtr model;
HRESULT hr = model.CreateInstance(__uuidof(MyObjX::MyObj));

#import "c:\program files\emblem modeller 3\MyObjx.dll" no_namespace
_MyObjPtr model(__uuidof(MyObj));

If this doesn't work, are you sure you're using 1) the correct smart pointer
type, and 2) the correct source for uuid ?

I'd say that given the uuid source is MyObj, it would be more logical if the
smart pointer was of type IMyObjPtr. But that is, of course, how it would
look if *I* implemented a server and used it.
 
G

Guest

IMyObjPtr isn't defined. _MyObjPtr is the only thing that is.
I've given up, to be honest, I've resigned myself that it's something
non-standard about the COM object. I've emailed the company to ask them and
if they don't email me back then I'm giving up.
 
O

Oleg Starodumov

In addition to Sigurd's message...
#import "c:\program files\emblem modeller 3\MyObjx.dll"
#include <tchar.h>

int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
MyObjX::_MyObjPtr model;
HRESULT hr = model.CreateInstance(__uuidof(MyObjX::MyObj));
if(hr == S_OK) MessageBox(NULL, _T("EMB Model successfully created"),
_T("COM test"), MB_OK); //it never is.
CoUninitialize();
}

So you run this application and it still throws an exception
inside CreateInstance call and does not reach the next line?

Can you try with the raw CoCreateInstance, requesting only IUnknown,
so that other interfaces are not yet involved?

What threading model is used by the COM object?

Regards,
Oleg

P.S. It is better to have the smart pointer in its own scope,
otherwise (in case of successful creation of the object instance)
it will be released after CoUninitialize call, thus causing problems.

Something like this is needed:

CoInitialize()
{
MyObjX::_MyObjectPtr model;
...
}
CoUninitialize()
 
G

Guest

as in this..?

#import "c:\program files\emblem modeller 3\embpredictx.dll" no_namespace
#include <tchar.h>
#include <objbase.h>

int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
IUnknown* iu;
GUID IID_EMBPredictX = {0x601EA0CD, 0xBB9B, 0x11D1,
{0x81, 0x58, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};

GUID CLSID_EMBPredictX = {0x601EA0D0, 0xBB9B, 0x11D1,
{0x81, 0x58, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};

HRESULT hr = CoCreateInstance(IID_EMBPredictX, NULL, CLSCTX_INPROC_SERVER,
IID_IUnknown,
(void**)&iu);

if(hr == S_OK) MessageBox(NULL, _T("EMB Model successfully created"),
_T("COM test"), MB_OK);
CoUninitialize();
}

it does the same thing (priv. instr.), when passing the IID_EMBPredictX, and
'class not registered' when with any other combination of swapping round the
CLSID_ and the IID_ and the IID_IUnknown.



Oleg Starodumov said:
In addition to Sigurd's message...
#import "c:\program files\emblem modeller 3\MyObjx.dll"
#include <tchar.h>

int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
MyObjX::_MyObjPtr model;
HRESULT hr = model.CreateInstance(__uuidof(MyObjX::MyObj));
if(hr == S_OK) MessageBox(NULL, _T("EMB Model successfully created"),
_T("COM test"), MB_OK); //it never is.
CoUninitialize();
}

So you run this application and it still throws an exception
inside CreateInstance call and does not reach the next line?

Can you try with the raw CoCreateInstance, requesting only IUnknown,
so that other interfaces are not yet involved?

What threading model is used by the COM object?

Regards,
Oleg

P.S. It is better to have the smart pointer in its own scope,
otherwise (in case of successful creation of the object instance)
it will be released after CoUninitialize call, thus causing problems.

Something like this is needed:

CoInitialize()
{
MyObjX::_MyObjectPtr model;
...
}
CoUninitialize()

Oleg Starodumov said:
In addition to Sigurd's message...
#import "c:\program files\emblem modeller 3\MyObjx.dll"
#include <tchar.h>

int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
MyObjX::_MyObjPtr model;
HRESULT hr = model.CreateInstance(__uuidof(MyObjX::MyObj));
if(hr == S_OK) MessageBox(NULL, _T("EMB Model successfully created"),
_T("COM test"), MB_OK); //it never is.
CoUninitialize();
}

So you run this application and it still throws an exception
inside CreateInstance call and does not reach the next line?

Can you try with the raw CoCreateInstance, requesting only IUnknown,
so that other interfaces are not yet involved?

What threading model is used by the COM object?

Regards,
Oleg

P.S. It is better to have the smart pointer in its own scope,
otherwise (in case of successful creation of the object instance)
it will be released after CoUninitialize call, thus causing problems.

Something like this is needed:

CoInitialize()
{
MyObjX::_MyObjectPtr model;
...
}
CoUninitialize()
 

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