During an export to a connected directory, a problem can occur if the export session times out. In this event, resources are not released for unmanaged objects. Normally, when an export is completed, the EndExport method is called, which releases these resources. However, during a time-out, the object on which the EndExport method is normally called is unreachable.

To mitigate this problem, you must add a destructor in each class that you can call to clean up unmanaged resources when the export times out. The destructor contains cleanup code that unloads the application domain and aborts the export. For more information, see Destructors.

In your extension application, this problem might occur in the classes that implement the following interfaces:

  • BeginExport

  • GenerateImportFile

If there are multiple destructors in the extension, there is no guarantee that they will be called in a certain order. For that reason, you should not make a reference between two classes that have destructors because one class might be destroyed before the other class can use its resources.

An example of how to use a destructor and cleanup code is shown in the following example.

Using the try-finally Statement

Another good practice is to use the try-finally block in all your extensions. When you use this statement, any managed resources that are allocated in the try block are cleaned up in the finally block. You should use the try-finally block at single function entry points, such as GenerateImportFile or DeliverExportFile. For more information, see try-finally.

Code Example for Data Source Extensions Used for Export

The following C# code example shows how to use a destructor, a cleanup statement, and a try-finally block.

C#  Copy Code
using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Collections.Specialized;
using Microsoft.MetadirectoryServices;

namespace Miis_CallExport
{
	public class MACallExport :  
		IMAExtensibleFileImport, 
		IMAExtensibleCallExport
	{

		bool m_fInitialized; // Used to indicate if we have initialized resources

		//
		// Constructor
		//
		public MACallExport(
			)
		{
			//
			// TODO: Add constructor logic here
			//

			// Set member variable indicating we have initialized class
			m_fInitialized = true;
	}

		//
		// Destructor
		//
		~MACallExport()
		{
			if (m_fInitialized)
				Cleanup(true);
	}

		//
		//  Generic cleanup function used for import and exports.
		//  Cleanup is always called regardless, even if an
		//  exception is thrown from the import and export interfaces.
		//  It is also called in the case when the function times out.
		//  In this case it is called from the destructor (fFromDestructor 
		//  is set to true) and it should not rely on the 
		//  existence of other object instances, since garbage 
		//  collection is non-deterministic.
		//
		public void Cleanup(
			bool fFromDestructor
			)
		{
			if (!fFromDestructor)
			{
				//
				// TODO: Add cleanup logic.  Member objects of this 
				// class instance can be accessed. 
				//		
		}

			//
			// TODO: Add cleanup logic for unmanaged resources of this class.
			//		

			// Set member variable indicating we have released resources.
			m_fInitialized = false;
	}

		public void GenerateImportFile( 
			string					filename, 
			string					connectTo, 
			string					user, 
			string					password, 
			ConfigParameterCollection   configParameters,
			bool						fullImport, 
			TypeDescriptionCollection   types,
			ref string				customData 
			)
		{
			try
			{
				//
				// TODO: Add logic here to create import file.
				//
		}
			finally
			{
				//
				// TODO: Add code for import specific cleanup.
				//

				//
				// Call cleanup code to deallocate resources.
				//
				Cleanup(false);
		}
	}

		public void BeginExport( 
			string					connectTo, 
			string					user, 
			string					password,
			ConfigParameterCollection   configParameters,
			TypeDescriptionCollection   types
			)
		{
			//
			// TODO: Add code to initialize an export run.
			//		
	}

		public void ExportEntry( 
			ModificationType	modificationType, 
			string[]			changedAttributes,
			CSEntry			 csentry 
			)
		{
			//
			// TODO: Add code to export one entry to the target.
			//		
	}

		public void EndExport(
			)
		{
			//
			// TODO:  Add code for export specific cleanup.
			//

			//
			// Call cleanup code to deallocate resources.
			//
			Cleanup(false);
	}
}
}

See Also