Задача следущая.
Необходимо в .Net создать обертку для набора COM-объектов, точнее некоторых их свойств, методов, событий.
Делаю так:
Я инстанцирую объект по ProgID(конфигурируемый)
Type tp = Type.GetTypeFromProgID(progID);
object COMObject = Activator.CreateInstance(tp);
А вот с событиями кажется проблема.
Если бы COM-Объект был один и тот-же, а не набор, то, как описывается здесь, через oleview я бы подсмотрел GUID интерфеса событий,
объявил бы в design-time свой интерфес приемника (IMySinkEvents),реализовал IMySinkEvents в классе-приемнике событий и связал бы COM-объект с моим приемником событий как то так:
IConnectionPointContainer icpc = (IConnectionPointContainer)COMObject;
IConnectionPoint connectionPoint;
int cookie = 0;
Guid g = typeof(IMySinkEvents).GUID;
icpc.FindConnectionPoint(ref g, out connectionPoint);
connectionPoint.Advise(MySinkEventsInstance, out cookie);
В моем случае GUID у COM-объектов разные и видимо приходится искать способ как в run-time "исследовать" COM-объект, чтобы найти по списку названий событий GUID интерфейса, в котором определены эти события.
Также в run-time объявить интерфейс приемника событий, реализовать его в своем классе-приемникеи как и в первом случае связать его с COM-объектом.
Как динамически объявлять типы и создавать объекты я представляю, а вот как "исследовать" COM-объект в run-time идей пока нет
и google молчит (м.б. не так спросил).
Интересуюсь, я на правильном пути? Если, да то как добраться до GUID и описания интрерфейса событий у COM -объекта
Re: run-time подписка на события набора COM - объектов
Здравствуйте, PeterPan, Вы писали:
PP>Как динамически объявлять типы и создавать объекты я представляю, а вот как "исследовать" COM-объект в run-time идей пока нет
Такого рода информацию получают из библиотеки типов COM-объекта — при её наличии, разумеется. Начинать от ITypeLib(2) к ITypeInfo. Чего-то готового для этого в BCL я не видел.
"Нормальные герои всегда идут в обход!"
Re[2]: run-time подписка на события набора COM - объектов
Здравствуйте, Jolly Roger, Вы писали:
JR>Здравствуйте, PeterPan, Вы писали:
PP>>Как динамически объявлять типы и создавать объекты я представляю, а вот как "исследовать" COM-объект в run-time идей пока нет
JR>Такого рода информацию получают из библиотеки типов COM-объекта — при её наличии, разумеется. Начинать от ITypeLib(2) к ITypeInfo. Чего-то готового для этого в BCL я не видел.
Кажется это те самые ключевые слова для гугла, которые я искал. Буду изучать, спасибо
Re: run-time подписка на события набора COM - объектов
Здравствуйте, PeterPan, Вы писали:
PP>Также в run-time объявить интерфейс приемника событий, реализовать его в своем классе-приемникеи как и в первом случае связать его с COM-объектом.
Многие COM объекты предоставляют события через наследника IDispatch — часто можно подписать именно его.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[2]: run-time подписка на события набора COM - объектов
Здравствуйте, Jolly Roger, Вы писали:
JR> Чего-то готового для этого в BCL я не видел.
Впрочем, кое-что кажется есть. Например, класс TypeLibConverter в System.Runtime.InteropServices может оказаться полезным. Так-же в System.Windows.Forms.Design есть класс.AxImporter, посмотрите.
"Нормальные герои всегда идут в обход!"
Re: run-time подписка на события набора COM - объектов
Здравствуйте, PeterPan, Вы писали:
PP>Как динамически объявлять типы и создавать объекты я представляю, а вот как "исследовать" COM-объект в run-time идей пока нет PP>и google молчит (м.б. не так спросил).
PP>Интересуюсь, я на правильном пути? Если, да то как добраться до GUID и описания интрерфейса событий у COM -объекта
Есть такие интерфейсы IProvideClassInfo и IProvideClassInfo2 (как и слова для поиска). Если они у объекта есть, то задача получения интересующих тебя сведений упрощается.
[Guid("00020400-0000-0000-c000-000000000046"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDispatch
{
int GetTypeInfoCount();
ITypeInfo GetTypeInfo([MarshalAs(UnmanagedType.U4)] int iTInfo,
[MarshalAs(UnmanagedType.U4)] int lcid);
[PreserveSig]
int GetIDsOfNames(ref Guid riid,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)]
string[] rgsNames, int cNames, int lcid,
[MarshalAs(UnmanagedType.LPArray)] int[] rgDispId);
[PreserveSig]
int Invoke(int dispIdMember, ref Guid riid,
[MarshalAs(UnmanagedType.U4)] int lcid,
[MarshalAs(UnmanagedType.U4)] int dwFlags,
ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
[Out, MarshalAs(UnmanagedType.LPArray)] object[] pVarResult,
ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo,
[Out, MarshalAs(UnmanagedType.LPArray)] IntPtr[] pArgErr);
}
получаем ITypeInfo и ITypeLib для COM-объекта
Type tp = Type.GetTypeFromProgID(progID);
object comObject = Activator.CreateInstance(tp);
IDispatch dispatch = comObject as IDispatch;
System.Runtime.InteropServices.ComTypes.ITypeInfo ppTINF = null;
System.Runtime.InteropServices.ComTypes.ITypeLib ppTLB= null;
int pIndex = 0;
if (dispatch != null)
{
ppTINF = dispatch.GetTypeInfo(0, 0);
ppTINF.GetContainingTypeLib(out ppTLB, out pIndex);
}
else
{
throw new InvalidComObjectException();
}
исследуем типы из библиотеки объектов
List<System.Runtime.InteropServices.ComTypes.TYPEATTR> list =
new List<System.Runtime.InteropServices.ComTypes.TYPEATTR>();
int i = 0;
System.Runtime.InteropServices.ComTypes.ITypeInfo item = null;
while (i < typeLib.GetTypeInfoCount())
{
typeLib.GetTypeInfo(i++, out item);
IntPtr pTypeAttr;
item.GetTypeAttr(out pTypeAttr);
list.Add(
(System.Runtime.InteropServices.ComTypes.TYPEATTR) Marshal.PtrToStructure(pTypeAttr,
typeof(System.Runtime.InteropServices.ComTypes.TYPEATTR)));
}
return list.ToArray();
структура System.Runtime.InteropServices.ComTypes.TYPEATTR содержит информацию о типе, в т.ч. guid.
Остается объявить в run-time интерфейс событий и реализовать в классе приемнике событий.