Hello folks or guys from MS can help,
My code structure like the following using VC++ :
CIrDlg::OnInitDialog(){
.....
m_pWaitForMessageThread = AfxBeginThread(WaitForMessage,
this); //create a thread.....
}
ClrDlg::WaitForMessage(){
AxCOM::Class2 * pObj = new AxCOM::Class2(); //AxCOM is managed component;
hRes = CoCreateInstance(clsid,NULL,CLSCTX_ALL,iid,
reinterpret_cast<void**>(&pObj));pObj->Logon(user, logon)
}
Error message:An unhandled exception of type 'System.AccessViolationException' occurred in Unknown Module.Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Anyone know the reason Thanks in advance.
Kevin Zhang

CoCreateInstance is called in VS 2005 and Multithreading, Urgent help !!!
kayda
Nikhil,
Thanks. In fact, the code that i posted works ok, just can not figure out the CPU consumption problem.
If I stick to my code, which means that unmanaged MFC application try to access COM component , right another, the COM component is managed or Unmanaged
Thanks again,
Kevin
Axelino
Nikhil ,
right. If I create a managed application using VC++ and put the above code, it work very well.
However, If I want to access the component from MFC unmanaged application, Do you have any clues
Thanks, Kevin
serpentara
Looks like you are marshalling a managed object into unmanaged (com) code. You need to convert the managed type into unmanaged object and back again. You can use the System.Marshal class for this. For more info look at http://msdn.microsoft.com/library/default.asp url=/library/en-us/cpref/html/frlrfsystemruntimeinteropservicesmarshalclasstopic.asp
Hope this helps!
wizard4u
Kevin,
I am a little confused now... in the first post you suggested that the COM component was a managed COM component.
AxCOM::Class2 * pObj = new AxCOM::Class2(); //AxCOM is managed component;
But, moving on... Is the VC++ app a CLR managed app in which case adding a reference to the applicaiton to the COM component, will create a default Interop Wrapper. (Right click on the project in solution explorer-> References -> Add new reference -> COM objects - > your com component.
For further info on using the Interop wrapper by the above method in c++ look at http://msdn2.microsoft.com/en-us/library/8989aw26(VS.80).aspx
If you want to write a Custom Runtime Callable Wrapper (Which is what you seem to want) look at http://msdn2.microsoft.com/en-us/library/f31k2c87(VS.80).aspx.
Dont hesitate to mail/post if you need help!. If you can post some more code, maybe we can assist you better.
lewie
Kevin,
I think I am missing a trick here....
1) If the app is an MFC app, its a unmanged application and therfore you cant add a reference to a com component. I assume what you meant was a WinForms application.
2) The code to invoke a COM component using the default interop wrapper shouldnt be so complex. In fact I dont think the above code is going to work at all and can be done in half the number of lines. Take a look at http://msdn2.microsoft.com/en-us/library/8989aw26(VS.80).aspx on how a COM component should be invoked in VC++ Managed app using the default CCW. (Add reference == tlbimp, in the given example you need to add #using<Interop.Axapta...dll>)
Your code should look like
#using <Interop.AxaptaCOMConnector.1.2.dll>
using namespace AxaptaCOMConnector;
using namespace System;
..
...
AxaptaCOMConnector::IAxapta2^ pAxObjInterFace = dynamic_cast<AxaptaCOMConnector::IAxapta2^>(gcnew AxaptaCOMConnector::Axapta2Class()); //create com object and cast to appropriate interface this should call QueryInterface on the COM object.
String^ user = "user"; // declare a string on managed heap
String^ pwd = "pwd";
pAxObjInterFace->Logon(user,pwd); // the proxy in Interop.Axapta.... will marshall code for you.
System::Runtime::InteropServices::Marshal::ReleaseCOMObject(pAxObjInterFace);
(^ == handle to object on managed heap, gcnew == allocate object on managed heap)
Shout if you need help!.
tanha
Kevin,
When you register the managed COM component using regasm specify the /tlb option to generate a type library.
eg : regasm MyManagedCOM.dll /tlb:com.MyManagedCOM.tlb
in your C++ app put in the following pre-processor
#import "<full path>\com.MyManagedCOM.tlb" named_guids raw_interfaces_only
compiling this should generate a .tlh file which contains a proxy to call the managed COM.
To create a managed object:
CoInitialize(NULL); //Initialize all COM Components
// <namespace>::<InterfaceName>
MyCom::IMyDotNetInterfacePtr pDotNetCOMPtr;
// CreateInstance parameters
// e.g. CreateInstance (<namespace::CLSID_<ClassName>)
HRESULT hRes =
pDotNetCOMPtr.CreateInstance(MyCOM::CLSID_MyDotNetClass);
if (hRes == S_OK)
{
BSTR str;
pDotNetCOMPtr->SomeCOMFunction ();
//call .NET COM exported function
}
CoUninitialize (); //DeInitialize all COM Components
the proxy will contain the code to marshall data to and fro.
hope this helps!
biyikli79
Kevin,
Cant really tell you why it takes high CPU to execute without looking at the code for Logon(). But...
If the COM component is a managed object dont call CoCreateInstance. The code snippet I sent above, should make your code look something like this...
AxaptaCOMConnector::IAxapta2 pAxObjInterFace;
Hresult hres = pAxObjInterFace.CreateInstance(clsid);
pAxObjInterFace->Logon(user,passwd);
The proxy created for you (in the tlh) file would take care of object creation in the createinstance method. You need to call Marhsal.ReleaseCOMObject(pAxObjInterFace ) to ensure that the reference count is decremented.
To see what the performance problem in Logon() is you can use Lutz Roeder's Reflector tool on the dll to look at the code.
Nikhil
turgay
Nikhil,
Thanks a lot. I still can not get result. now, I start from the beginning. May I am stupid. I do not know whether the component dll is managed object or not. I did not find the AxaptaCOMConnector.tlb file, which is imported. When I use tlbexp.exe there are some error:
TlbExp:error TX0000: could not load file or assembly 'filename' or one of its dependencies. the module was expected to contain an assembly manifest.
Because the dll is not .net assembly, so there is NO method CreateInstance for pAxobjInterFace object.
Thanks again. Please give more highlightments if you can.
Kevin
rammanju
Vivek Jain
Nikhil,
Thanks for quick response. sorry for confused information. I try this code in a small program which just a dialog window. The problem is same.
I use VC++ in VS 2005 to generate a program based on MFC dialog window and add reference to the COM component. You are right, the system create a default interop Wrapper called Interop.AxaptaCOMConnector.1.2.dll. The following code:
CLSID clsid;
IID iid;
CLSIDFromString(L
"{80F444A3-46FF-11D2-8459-0008C7A0D1EA}", &clsid);IIDFromString(L
"{80F444AE-46FF-11D2-8459-0008C7A0D1EA}", &iid);CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
AxaptaCOMConnector::IAxapta2* pAxObjInterFace = new AxaptaCOMConnector::Axapta2Class();BSTR bstr1 = SysAllocString(L
"admin");VARIANT vStr;
vStr.vt = VT_BSTR;
vStr.bstrVal = bstr1;
System::Object
__gc *user = System::Runtime::InteropServices::Marshal::GetObjectForNativeVariant(System::IntPtr(&vStr));bstr1 = SysAllocString(L
"xyz");vStr.bstrVal = bstr1;
System::Object
__gc *passwd = System::Runtime::InteropServices::Marshal::GetObjectForNativeVariant(System::IntPtr(&vStr));hRes = CoCreateInstance(clsid,NULL,CLSCTX_ALL,iid,
reinterpret_cast<void**>(&pAxObjInterFace));pAxObjInterFace->Logon2(user,passwd); //problem here, I guess that the pointer can not find the function implementation in the USER library . Just guess
pAxObjInterFace->ReferenceEquals(user,passwd); //WORK OK, since the function is the system library.
CoUninitialize();
br-
kevin
rokhead
Nikhil ,
Thanks. I still do not have luck.
The following is my code example:
AxaptaCOMConnector::IAxapta2* pAxObjInterFace;
hRes = CoCreateInstance(clsid,NULL,CLSCTX_ALL,iid,reinterpret_cast<void**>(&pAxObjInterFace));
pAxObjInterFace->Logon(user,passwd); //NOT OK , program runs successfully , but CPU consume 50%. Even I exit from the main program, there are somthing runing in the background. It seems that the object pointer lost of control. this method is provided by COMponent.
pAxObjInterFace->ReferenceEquals(user,passwd); //OK the method is provided by system.
Do you think what the main reason is
Thanks again.
Kevin
aschapiro
Nikhil,
Thanks a lot. Eventully, we solved the problem. It is managed object. Just like your said. the solution is that I did not use CoCreateInstance, but called managed code from unmanaged code.
Thanks again,
Kevin
ChrisTB
Yes, I think I have a better idea now of whats happening.
Can you confirm that the parameter to the COM function is a System::Object If yes.. the COM object is a managed object. When you create it, the CLR will be loaded in process with your app.
I am testing this out now.. but I think the CPU utilisation you see is the CLR coming in process with your application when you call the managed functions. Subsequent calls to the function shouldnt take a high CPU. can you try that
Vanna
Nikhi, Thanks. I will try.
I think that my question is How the unmanaged code calls the methods in a managed COM component.
for pObj->Logon(), the parameter require System::Object __gc* type (in C#, the parameters of the method actually are String type). I am new about marshalling, how to marshal theses parameters forward and back Could you give hints more detail
Thanks again.