in

andy vt's tools & blog

automating lazy

This Blog

Syndication

andy vt's blog

Loading Unregistered COM objects with .NET

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;
}

 

Comments

No Comments
@2008 andy vt
Powered by Community Server (Non-Commercial Edition), by Telligent Systems