Ho creato un semplice oggetto COM con il seguente IDL:
// ComObject.idl : IDL source for ComObject
//
// This file will be processed by the MIDL tool to
// produce the type library (ComObject.tlb) and marshalling code.
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(1C0C9AB2-4388-4E1A-A897-D63DD16910AC),
dual,
nonextensible,
pointer_default(unique)
]
interface IComClass : IDispatch{
[id(1)] HRESULT CalculateArea(FLOAT a, FLOAT b, [out] FLOAT* area);
};
[
uuid(F687E8E6-C714-404B-B946-57DFD49D1D1A),
version(1.0),
]
library ComObjectLib
{
importlib("stdole2.tlb");
[
uuid(916BBACF-990F-44DC-80B2-AD2FF5368E57)
]
coclass ComClass
{
[default] interface IComClass;
};
};
A questo punto per creare una istanza di IComClass ed invocare il metodo CalculateArea:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace LoadingUnregisteredCOMObjectsWithDotNET
{
class Program
{
static Guid IID_IUNKNOWN = new Guid("00000000-0000-0000-C000-000000000046");
static Guid IID_COMCLASS = new Guid("916BBACF-990F-44DC-80B2-AD2FF5368E57");
static Guid IID_CLASSFACTORY = new Guid("00000001-0000-0000-c000-000000000046");
static Guid IID_IUNKNOW = new Guid("00000000-0000-0000-C000-000000000046");
[DllImport("kernel32", EntryPoint = "LoadLibrary", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32")]
public static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32", EntryPoint = "GetProcAddress", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
delegate int DllGetClassObject(ref Guid clsid, ref Guid iid, [Out, MarshalAs(UnmanagedType.Interface)] out IClassFactory classFactory);
[Guid("00000001-0000-0000-c000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
internal interface IClassFactory
{
void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppvObject);
void LockServer(bool fLock);
}
[System.Runtime.InteropServices.ComImport]
[System.Runtime.InteropServices.Guid("1C0C9AB2-4388-4E1A-A897-D63DD16910AC")]
public interface IComClass
{
[System.Runtime.InteropServices.DispId(1)]
void CalculateArea(float a, float b, ref float area);
}
static void Main(string[] args)
{
IntPtr library = IntPtr.Zero;
library = LoadLibrary("ComObject.dll");
IntPtr ptr = GetProcAddress(library, "DllGetClassObject");
var dllGetClassObjectCallback = (DllGetClassObject)Marshal.GetDelegateForFunctionPointer(ptr, typeof(DllGetClassObject));
IClassFactory classFactory;
var hresult = dllGetClassObjectCallback(ref IID_COMCLASS, ref IID_CLASSFACTORY, out classFactory);
Object ppvObject;
classFactory.CreateInstance(null, ref IID_IUNKNOW, out ppvObject);
IComClass comClass = (IComClass)ppvObject;
float area = 0f;
comClass.CalculateArea(34f, 67f, ref area);
FreeLibrary(library);
}
}
}
LoadingUnregisteredCOMObjectsWithDotNET.zip
ComObject.zip