Skip to content

Instantly share code, notes, and snippets.

@michel-pi
Last active December 23, 2018 08:42
Show Gist options
  • Save michel-pi/c5be51e87db649bfb01f2e788e6942c9 to your computer and use it in GitHub Desktop.
Save michel-pi/c5be51e87db649bfb01f2e788e6942c9 to your computer and use it in GitHub Desktop.
Import methods from .dll's at runtime
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace System.Runtime.InteropServices
{
public static class DynamicImport
{
[DllImport("kernel32.dll", EntryPoint = "GetProcAddress", SetLastError = true, CharSet = CharSet.Ansi)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procname);
[DllImport("kernel32.dll", EntryPoint = "LoadLibraryW", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", EntryPoint = "GetModuleHandleW", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr GetModuleHandle(string modulename);
public static IntPtr ImportLibrary(string libraryName)
{
if (libraryName == string.Empty) throw new ArgumentOutOfRangeException(nameof(libraryName));
IntPtr hModule = GetModuleHandle(libraryName);
if(hModule == IntPtr.Zero)
{
hModule = LoadLibrary(libraryName);
}
if (hModule == IntPtr.Zero)
{
throw new DynamicImportException("DynamicImport failed to import library \"" + libraryName + "\"!");
}
else
{
return hModule;
}
}
public static IntPtr ImportMethod(IntPtr moduleHandle, string methodName)
{
if (moduleHandle == IntPtr.Zero) throw new ArgumentOutOfRangeException(nameof(moduleHandle));
if (string.IsNullOrEmpty(methodName)) throw new ArgumentOutOfRangeException(nameof(methodName));
IntPtr procAddress = GetProcAddress(moduleHandle, methodName);
if (procAddress == IntPtr.Zero)
{
throw new DynamicImportException("DynamicImport failed to find method \"" + methodName + "\" in module \"0x" + moduleHandle.ToString("X") + "\"!");
}
else
{
return procAddress;
}
}
public static IntPtr ImportMethod(string libraryName, string methodName)
{
return ImportMethod(ImportLibrary(libraryName), methodName);
}
public static T Import<T>(IntPtr moduleHandle, string methodName)
{
var address = ImportMethod(moduleHandle, methodName);
return Marshal.GetDelegateForFunctionPointer<T>(address);
}
public static T Import<T>(string libraryName, string methodName)
{
var address = ImportMethod(libraryName, methodName);
return Marshal.GetDelegateForFunctionPointer<T>(address);
}
}
public class DynamicImportException : Win32Exception
{
public DynamicImportException()
{
}
public DynamicImportException(int error) : base(error)
{
}
public DynamicImportException(string message) : base(message + Environment.NewLine + "ErrorCode: " + Marshal.GetLastWin32Error())
{
}
public DynamicImportException(int error, string message) : base(error, message)
{
}
public DynamicImportException(string message, Exception innerException) : base(message, innerException)
{
}
protected DynamicImportException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment