I wrote this class to making things easier while invoking native dlls dynamicly. Read comments in the class to understand what it doing. There is a sample at the end of this article showing how to use this abstrract class.
/// <summary>
/// Encapsulate LoadLibrary and FreeLibrary functions for Kernel32.dll.
/// Note this is a abstract class targeting to be inherited by a derived class
/// which will encapsulating one or more function(s) for a given module file.
/// The advantage of making a dedicated class is,
/// the dll handle will always available as long as instance
/// of the derived class still available.
/// </summary>
public abstract class LoadLibraryBase:IDisposable
{
#region Fields
/// <summary>
/// Indicating whether the instance of this class has been disposed.
/// </summary>
protected bool IsDisposed=false;
#endregion//Fields
#region Methods
[DllImport("Kernel32")]
public static extern int GetProcAddress( int handle , String funcname );
[DllImport("Kernel32")]
public static extern int LoadLibrary( String dllFileName );
[DllImport("Kernel32")]
public static extern int FreeLibrary( int handle );
/// <summary>
/// Initializes a new instance of this class using the provided module name.
/// </summary>
/// <param name="moduleName">
/// The file name of the module, which can be either a library module (a .dll file)
/// or an executable module (an .exe file).
/// If the string specifies a full path, the constructor searches only that path for the module.
/// If the string specifies a relative path or a module name without a path,
/// the constructor uses a standard search strategy to find the module.
/// When specifying a path, be sure to use backslashes (\), not forward slashes (/).
/// If the string specifies a module name without a path and the file name extension is omitted,
/// the constructor appends the default library extension .dll to the module name.
/// To prevent the constructor from appending .dll to the module name,
/// include a trailing point character (.) in the module name string.
/// </param>
/// <exception cref="NullReferenceException">
/// The provided module name is not available.
/// </exception>
public LoadLibraryBase( string moduleName )
{
this.HandleToTheLoadedDll = LoadLibrary(moduleName);
if ( HandleToTheLoadedDll==0 )
{
throw new NullReferenceException(string.Format("File {0} not available." , moduleName));
}
}
/// <summary>
/// Destructor will only release unmanaged resources.
/// </summary>
~LoadLibraryBase()
{
this.Dispose(false);
}
/// <summary>
/// Get a delegate for the provided function name.
/// </summary>
/// <param name="functionName">
/// Name of the function in the module.
/// </param>
/// <param name="t">
/// The type of the delegate to be returned.
/// </param>
/// <returns>
/// A delegate instance that can be cast to the appropriate delegate type.
/// </returns>
/// <exception cref="System.ArgumentException">
/// The t parameter is not a delegate or is generic.
/// </exception>
/// <exception cref="System.ArgumentNullException">
/// The t parameter is null.
/// </exception>
protected Delegate GetDelegate( string functionName , System.Type t )
{
int addr = GetProcAddress(this.HandleToTheLoadedDll , functionName);
if ( addr == 0 )
throw new NullReferenceException(string.Format("Can not find function '{0}'" , functionName));
else
return Marshal.GetDelegateForFunctionPointer(new IntPtr(addr) , t);
}
protected void Dispose( bool disposing )
{
if ( !IsDisposed )
{
if ( disposing )
{
//Clean up managed resources here.
}
//Cleaning up unmanaged resources here.
FreeLibrary(this.HandleToTheLoadedDll);
}
IsDisposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion//Methods
#region Properties
protected int HandleToTheLoadedDll { get; set;}
#endregion//Properties
}
-------------------------------------------------------------------------------
Sample of how to use this class:
---------------------------------------------------------------------------------
/// <summary>
/// Encapsulate the 'MessageBoxA' function for user32.dll.
/// Note the advantage of making a dedicated class is that
/// the dll handle will always available as long as instance
/// of this class still available.
/// </summary>
/// <exception cref="NullReferenceException">
/// Either dll file name or fuction name is wrong.
/// </exception>
public class MyMssageBox : LoadLibraryBase
{
public MyMssageBox( ):base("User32.dll")
{
}
delegate int MsgBox( int hwnd , string msg , string cpp , int ok );
public void Show( string msg , string cpp , int ok )
{
var msgbox = ( MsgBox ) GetDelegate("MessageBoxA" , typeof(MsgBox));
msgbox(0 , msg , cpp , ok);
}
}