> Hi Carl.
>
[quoted text clipped - 5 lines]
> What else can I do to call managed code on a mixed mode DLL
> initialization?
Carl, I think it's OK now.
I called CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); on DllMain of one
of my DLLs when reason == DLL_PROCESS_ATTACH. Then I called CoUninitialize()
when read == DLL_PROCESS_DETACH.
Now the program is running! Thanks a lot, you made my weekend.
But in the output window I'm getting the inverse message that I had before:
Managed Debugging Assistant 'InvalidApartmentStateChange' has detected a
problem in 'c:\Fontes\QiCad.NET\QiCad.NET.exe'.
Additional Information: Thread is attempting to set the apartment state to
MTA, but it has already been set to STA.
Do you believe I should call CoInitializeEx in all my mixed mode DLLs?
Thanks again for your help.
Adriano.
AltoQi - Tecnologia Aplicada à Engenharia Adriano Coser Departamento de
Desenvolvimento Tel.: (48) 239-7000 ramal: 7069 e-mail: coser@altoqi.com.br
website: www.altoqi.com.br
>> Hi Carl.
>>
[quoted text clipped - 12 lines]
>
> -cd
Carl Daniel [VC++ MVP] - 30 Apr 2005 01:30 GMT
> Carl, I think it's OK now.
>
[quoted text clipped - 12 lines]
>
> Do you believe I should call CoInitializeEx in all my mixed mode DLLs?
Actually, as a general principle I don't believe you should ever try to
enter an apartment in a DLL unless you're doing it in a thread that your DLL
"owns" (creates and managed the lifetime of). Perhaps there's something
unique about your situation that requires it, but I'd try to get rid of the
requirement rather than tilting at windmills trying to find a way to honor
it.
-cd
Kapil Khosla [MSFT] - 30 Apr 2005 19:09 GMT
> Carl, I think it's OK now.
>
[quoted text clipped - 36 lines]
> >
> > -cd
No, you should never call a method from DllMain which has managed code in it
or calls another method with managed code. You can easily get into a loader
lock problem.
The recommended way to move code out of DllMain is to declare a global
managed object. In the constructor of that object you should call the code
which you were initially calling in DllMain. The module constructor will
initialize see this global and call the constructor.
Note: A managed object here is not a ref/value class object. You cannot
have global ref objects. Here managed object means a native class compiled
with /clr or under #pragma managed.
The reason is this works is because in mixed assemblies, the initializations
are done by the module constructor. It is very important to remember that the
module constructor for an assembly is called only if some managed code is
first executed either in the host assembly or in your Dll itself. If you dont
"use" that managed object you will never invoke the module constructor, thus
your constructor will never be called and data will be uninitialized.
Let me give you an example,
///////////////////////
cl /clr /LD /Zi 1.cpp
cl /clr /EHa t.cpp /Zi /link 1.lib
/////////////////////
/////////////////
//1.cpp
#pragma once
#include <stdio.h>
#include <windows.h>
class __declspec(dllexport) A
{
public:
A()
{
System::Console::WriteLine("Module constructor doing initialization based
on the global instance of the class A\n");
System::Console::WriteLine("Code from DllMain, now in constructor
executed\n");
}
void foo()
{
printf("foo called so that the linker knows not to throw away an unuse
object in t.cpp \n");
}
};
#pragma unmanaged
// Global instance of object
A obj;
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// REMOVE ALL MANAGED CODE FROM DLLMAIN.
return true;
}
///////////////////////////////
//t.cpp
#include <windows.h>
using namespace System;
#include <stdio.h>
#using "1.dll"
class __declspec(dllimport) A
{
public:
void foo();
};
int main()
{
LoadLibrary("1.dll");
A obj;
obj.foo();
}
Carl Daniel [VC++ MVP] - 01 May 2005 01:48 GMT
> No, you should never call a method from DllMain which has managed
> code in it or calls another method with managed code. You can easily
> get into a loader lock problem.
Note that he's calling CoInitializeEx, which, last I checked, has no managed
code in it. Of course, that alone does not mean it's safe to call it from
DllMain, and I make no claim that it is.
-cd
Kapil Khosla [MSFT] - 01 May 2005 08:01 GMT
> > No, you should never call a method from DllMain which has managed
> > code in it or calls another method with managed code. You can easily
[quoted text clipped - 5 lines]
>
> -cd
You are right. But it always makes me nervous when someone calls a method in
DllMain and that method potentially could have managed code which tries to
load the CLR.
The original method you mention of having code in the managed object's
constructor is much better and should work. Although I think the
interpretation of Adriano was not quite correct. He created a static object
inside the managed class but it should have been a global like the example I
posted so that the module constructor can do the initialization when the
assembly is loaded.
Thanks Carl.
Kapil