.NET Forum / Languages / Managed C++ / October 2004
baffled by exception
|
|
Thread rating:  |
Bonj - 12 Oct 2004 12:49 GMT 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!
Nicholas Paldino [.NET/C# MVP] - 12 Oct 2004 13:38 GMT 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.
 Signature - Nicholas Paldino [.NET/C# MVP] - mvp@spam.guard.caspershouse.com
> Hello. > Does anybody know if there is a difference between the way C# calls a COM [quoted text clipped - 26 lines] > > Cheers! Bonj - 12 Oct 2004 16:45 GMT > 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......
Sigurd Stenersen - 12 Oct 2004 17:27 GMT > //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.
 Signature Sigurd http://utvikling.com
Bonj - 12 Oct 2004 17:51 GMT I've done that with still the same exception
> > //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. Willy Denoyette [MVP] - 12 Oct 2004 22:26 GMT 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.
> I've done that with still the same exception > [quoted text clipped - 3 lines] >> >> Try using #import and smart pointers instead. Bonj - 13 Oct 2004 09:13 GMT 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++ ??
> 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 [quoted text clipped - 11 lines] > >> > >> Try using #import and smart pointers instead. Willy Denoyette [MVP] - 13 Oct 2004 21:00 GMT Well, if the problem was only with C# and MC++, I would think about COM interop in the CLR. But you also have the same problem using native C++, so no interop involved :-)
Willy.
> 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 [quoted text clipped - 16 lines] >> >> >> >> Try using #import and smart pointers instead. Nicholas Paldino [.NET/C# MVP] - 12 Oct 2004 13:40 GMT 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.
> Hello. > Does anybody know if there is a difference between the way C# calls a COM [quoted text clipped - 26 lines] > > Cheers! Richard Blewett [DevelopMentor] - 12 Oct 2004 14:24 GMT 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/<Ogp4wiFsEHA.2340@TK2MSFTNGP11.phx.gbl>
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.
Bonj - 12 Oct 2004 17:33 GMT 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?
> 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. > [quoted text clipped - 14 lines] > > Hope this helps. Richard Blewett [DevelopMentor] - 12 Oct 2004 17:49 GMT 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/<4A6755DD-2329-47A2-AD44-8A3E6B578C53@microsoft.com>
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?
Bonj - 12 Oct 2004 18:05 GMT 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
> 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. > [quoted text clipped - 11 lines] > 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? Bonj - 12 Oct 2004 18:09 GMT nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<4A6755DD-2329-47A2-AD44-8A3E6B578C53@microsoft.com>
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
Oleg Starodumov - 13 Oct 2004 11:27 GMT 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
Bonj - 13 Oct 2004 12:17 GMT 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(); }
> 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 Sigurd Stenersen - 13 Oct 2004 12:56 GMT > #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.
 Signature Sigurd http://utvikling.com
Bonj - 13 Oct 2004 13:23 GMT but thanks for your efforts anyway, and I like the no_namespace thing.
> > #import "c:\program files\emblem modeller 3\MyObjx.dll" > > MyObjX::_MyObjPtr model; [quoted text clipped - 9 lines] > smart pointer was of type IMyObjPtr. But that is, of course, how it would > look if *I* implemented a server and used it. Bonj - 13 Oct 2004 13:23 GMT 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.
> > #import "c:\program files\emblem modeller 3\MyObjx.dll" > > MyObjX::_MyObjPtr model; [quoted text clipped - 9 lines] > smart pointer was of type IMyObjPtr. But that is, of course, how it would > look if *I* implemented a server and used it. Oleg Starodumov - 13 Oct 2004 13:23 GMT In addition to Sigurd's message...
> #import "c:\program files\emblem modeller 3\MyObjx.dll" > #include <tchar.h> [quoted text clipped - 8 lines] > 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()
Bonj - 13 Oct 2004 15:33 GMT 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.
> In addition to Sigurd's message... > [quoted text clipped - 34 lines] > } > CoUninitialize()
> In addition to Sigurd's message... > [quoted text clipped - 34 lines] > } > CoUninitialize()
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|