CoCreateInstance is called in VS 2005 and Multithreading, Urgent help !!!

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




Answer this question

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

    OK, then why am I getting the same message (attempted to read or write protected memory) when I'm trying to trying to create a stored procedure using out of the box functionality in VS2005 I can create SP that select data without a problem, but when I try and create an insert procedure, even one as simple as one record with one variable, as soon as I close the Query Builder I get the same thing Arrrrgh! I'm not even coding anything by hand!

  • 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.

     



  • CoCreateInstance is called in VS 2005 and Multithreading, Urgent help !!!