vt96
asked on
Problem unloading mixed C++ DLL
I am currently writing a C++ mixed DLL containing both managed and unmanaged code with the purpose of implementing the extension interface of a legacy C++ application and using the advanced features of the .NET framework to exend the functionality of the application. I was able to load this DLL into the legacy application and use the .NET framework classes in my extension without problems except for unloading the extension. I noticed that when the application unloads the extension it is never unloaded cleanly. The DLL_PROCESS_DETACH is never called !!
While trying to precisly define the problem, I created a minimal extension without any managed functions, and it was loaded/unloaded without any problems, but when I add any managed function (even if it was an empty function) the extension does NOT unload. I tried to use the AppDomain.Unload() but without success. Is there a way to make such mixed application extension unload cleanly ?
While trying to precisly define the problem, I created a minimal extension without any managed functions, and it was loaded/unloaded without any problems, but when I add any managed function (even if it was an empty function) the extension does NOT unload. I tried to use the AppDomain.Unload() but without success. Is there a way to make such mixed application extension unload cleanly ?
What C++ version?
ASKER
Visual Studio 2005
Can you post some minimal code which allows to reproduce this problem?
ASKER
Here is the minimal code that shows the problem. It is commented to be illustrative.
#include "stdafx.h"
#using <mscorlib.dll>
using namespace AnvilCSharpExt;
static AFX_EXTENSION_MODULE TheDLL = { NULL, NULL };
// Switch to unmanaged mode for the DllMain
#pragma managed(push, off)
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(lpR eserved);
if (dwReason == DLL_PROCESS_ATTACH)
{
if (!AfxInitExtensionModule(T heDLL, hInstance))
return 0;
new CDynLinkLibrary(TheDLL);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
AfxTermExtensionModule(Stu bDLLDLL);
}
return 1;
}
// Backto managed
#pragma managed(pop)
extern "C" {
void WINAPI AnExtensionInterfaceFuncti on()
{
// Although this is an empty function that will be called by the application that loads this extension, making it a managed function prevents the DLL from unloading properly
}
} //extern "C"
#include "stdafx.h"
#using <mscorlib.dll>
using namespace AnvilCSharpExt;
static AFX_EXTENSION_MODULE TheDLL = { NULL, NULL };
// Switch to unmanaged mode for the DllMain
#pragma managed(push, off)
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(lpR
if (dwReason == DLL_PROCESS_ATTACH)
{
if (!AfxInitExtensionModule(T
return 0;
new CDynLinkLibrary(TheDLL);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
AfxTermExtensionModule(Stu
}
return 1;
}
// Backto managed
#pragma managed(pop)
extern "C" {
void WINAPI AnExtensionInterfaceFuncti
{
// Although this is an empty function that will be called by the application that loads this extension, making it a managed function prevents the DLL from unloading properly
}
} //extern "C"
So, client should load Dll using LoadLibrary and call AnExtensionInterfaceFuncti on? And when FreeLibrary is called, DllMain with DLL_PROCESS_DETACH is not called?
ASKER
Thank you for your help.
Yes, the client load the extension dynamically uysing LoadLibrary, and when freeing the Library using FreeLibrary the Dllmain() with DLL_PROCESS_DETACH is never called if any "managed" function was previously called in the DLL either directly or indirectly (through another unmanaged function). If the DLL does not have any managed function that was called between LoadLibrary and FreeLibrary, then it is freed normally and the DLL_PROCESS_DETACH of DllMain() is called as usual.
Yes, the client load the extension dynamically uysing LoadLibrary, and when freeing the Library using FreeLibrary the Dllmain() with DLL_PROCESS_DETACH is never called if any "managed" function was previously called in the DLL either directly or indirectly (through another unmanaged function). If the DLL does not have any managed function that was called between LoadLibrary and FreeLibrary, then it is freed normally and the DLL_PROCESS_DETACH of DllMain() is called as usual.
I will try to test this some time later. I added this question to my bookmarks, cannot promise immediate result.
My first guess is that once managed function is called, some managed instances are allocated. They are subject of garbage collecting, this prevents library to be unloaded immediately. Even if function call doesn't do anything, loading library requires .NET to read library metadata, this allocates a lot of managed instances. Possibly unloading managed library is unpredictable like releasing of garbage-collected objects.
My first guess is that once managed function is called, some managed instances are allocated. They are subject of garbage collecting, this prevents library to be unloaded immediately. Even if function call doesn't do anything, loading library requires .NET to read library metadata, this allocates a lot of managed instances. Possibly unloading managed library is unpredictable like releasing of garbage-collected objects.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you for your help