Microsoft KB Archive/301357

= PRB: DLLs Not Unloaded After Calling CoFreeUnusedLibraries =

Article ID: 301357

Article Last Modified on 12/25/2006

-

APPLIES TO

 Microsoft COM+ 2.0 Standard Edition, when used with:  Microsoft Windows 95

 Microsoft Windows 98 Standard Edition

 Microsoft Windows Millennium Edition

 Microsoft Windows 2000 Standard Edition</li></ul>

 Microsoft Windows NT 4.0</li></ul> </li></ul>

-

<div class="notice_section">

This article was previously published under Q301357

<div class="symptoms_section">

SYMPTOMS
Dynamic-link libraries (DLLs) that are not in use may not be unloaded from the process space after calling the CoFreeUnusedLibraries function.

<div class="cause_section">

CAUSE
This problem occurs when the application still has references to the components in the DLL, or when the application releases all the references to a DLL but does not make a subsequent call to CoFreeUnusedLibraries.

<div class="resolution_section">

RESOLUTION
CoFreeUnusedLibraries does not immediately release DLLs that have no active object. There is a ten minute delay for multithreaded apartments (MTAs) and neutral apartments (NAs). For single-threaded apartments (STAs), there is no delay. The ten minute delay for CoFreeUnusedLibraries is to avoid multithread race conditions caused by unloading a component DLL.

To work around the problem, make a second call to CoFreeUnusedLibraries after ten minutes, or make periodic calls to CoFreeUnusedLibraries. For applications that run for long periods, such as Windows NT Service applications, calling CoFreeUnusedLibraries periodically ensures that DLLs that are not being used are unloaded.

Another workaround is to call CoUninitialize, which closes the COM library and releases all resources used by the current thread.

<div class="status_section">

STATUS
This behavior is by design.

<div class="moreinformation_section">

Steps to Reproduce Behavior
The following example uses the Microsoft XML Parser version 3 to demonstrate this behavior. This parser can be downloaded and installed from the following Microsoft Developer Network (MSDN) Web site:

http://msdn.microsoft.com/xml

<ol> Create an empty Win32 Console Application in Microsoft Visual C++ 6.0.</li>  Save the following code as main.cpp and add it to the project:
 * 1) include <stdio.h>
 * 2) include <conio.h>

using namespace MSXML2;
 * 1) import &quot;msxml3.dll&quot; named_guids raw_interfaces_only

// Global instance to force load/unload of OLE. struct InitOle { InitOle { ::CoInitialize(NULL); } ~InitOle { ::CoUninitialize;  } } _init_InitOle_;

// Function declarations. inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);};

void main {

try {       printf( &quot;Note that the msxml3.dll is not loaded yet. Press any key to start the test.\n\n&quot; ); _getch;

// Create an instance of DOMDocument. This will load Msxml3.dll into the process. IXMLDOMDocument *pDoc = NULL; HRESULT hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,           IID_IXMLDOMDocument, (LPVOID*)&pDoc);

TESTHR(hr);

// Release the reference. if (pDoc) pDoc->Release; // Free unused resources. CoFreeUnusedLibraries; printf( &quot;Now the DLL is loaded into the process. Monitor the process and note that the DLL will not be released even after 10 minutes. Then press any key to continue..\n\n&quot; ); _getch;

// Second call. CoFreeUnusedLibraries; printf( &quot;Now the DLL should have been unloaded. Press any key to finish.\n\n&quot; ); _getch;

}   catch(_com_error &e) {       printf(&quot;Com Error:\n&quot;); printf(&quot;Code = %08lx\n&quot;, e.Error); printf(&quot;Code meaning = %s\n&quot;, (char*) e.ErrorMessage); printf(&quot;Source = %s\n&quot;, (char*) e.Source); printf(&quot;Error Description = %s\n&quot;, (char*) e.Description); } }                   </li> Run the application and use a utility, such as Process Explorer from Sysinternals (see &quot;References&quot;), to monitor the loading and unloading of Msxml3.dll.</li></ol>

<div class="references_section">