COM is very convenient, but sometimes it isn't desirable (or possible) to register a component for use in an application. Geraint Davies provided a solution for C++ developers, but since I generally try to avoid writing unmanaged code it was necessary to figure out how to translate his e.g. into C#. The full source for loading unregistered COM objects and managing lifecycle is available in SVN, but since it took me a little while to figure out that the trick to making it go was using "GetDelegateForFunctionPointer" the translated method is below.
Enjoy.
//http://www.gdcl.co.uk/2011/June/UnregisteredFilters.htm
public object CreateObjectFromPath(string dllPath, Guid clsid, bool setSearchPath)
{
object createdObject = null;
IntPtr lib = IntPtr.Zero;
if (_libsLoaded.ContainsKey(dllPath))
lib = _libsLoaded[dllPath];
else
{
//some dlls have external dependancies, setting the search path to its location should assist with this
if (setSearchPath)
{
NativeMethods.SetDllDirectory(Path.GetDirectoryName(dllPath));
}
lib = NativeMethods.LoadLibrary(dllPath);
if (setSearchPath)
{
NativeMethods.SetDllDirectory(null);
}
}
if (lib != IntPtr.Zero)
{
//we need to cache the handle so the COM object will work and we can clean up later
_libsLoaded[dllPath] = lib;
IntPtr fnP = NativeMethods.GetProcAddress(lib, "DllGetClassObject");
if (fnP != IntPtr.Zero)
{
DllGETCLASSOBJECTInvoker fn = Marshal.GetDelegateForFunctionPointer(fnP, typeof(DllGETCLASSOBJECTInvoker)) as DllGETCLASSOBJECTInvoker;
object pUnk = null;
int hr = fn(clsid, IID_IUnknown, out pUnk);
if (hr >= 0)
{
IClassFactory pCF = pUnk as IClassFactory;
if (pCF != null)
{
hr = pCF.CreateInstance(null, IID_IUnknown, out createdObject);
}
}
}
else
{
throw new Win32Exception();
}
}
else
{
throw new Win32Exception();
}
return createdObject;
}