08/01/2014
Доступ к COM-приложениям из Таблицы исполняющихся объектов (ROT)
Вот тема, которая то и дело всплывает: как перейти к определенному экземпляру COM-приложения, если есть несколько экземпляров имеющих аналогичный ProgId? Вызов GetActiveObject (progId) может вернуть только один объект, так что нет никакого способа, чтобы выбрать нужный конкретный экземпляр.Обойти это ограничение можно используя Таблицу исполняющихся объектов (Running Object Table), которая может предоставить вам доступ к каждому экземпляру COM, работающему на машине.
Вот пример кода на C#, который показывает, как добиться этого:
Код - C#: [Выделить]
- [DllImport("ole32.dll")]
- static extern int CreateBindCtx(
- uint reserved,
- out IBindCtx ppbc);
- [DllImport("ole32.dll")]
- public static extern void GetRunningObjectTable(
- int reserved,
- out IRunningObjectTable prot);
- // Не забываем: using System.Runtime.InteropServices.ComTypes
- // Получение всех исполняющихся экземпляров из ROT
- private List<object> GetRunningInstances(string[] progIds)
- {
- List<string> clsIds = new List<string>();
- // Получение clsid для приложения
- foreach (string progId in progIds)
- {
- Type type = Type.GetTypeFromProgID(progId);
- if(type != null)
- clsIds.Add(type.GUID.ToString().ToUpper());
- }
- // Получение Таблицы исполняющихся объектов (ROT) ...
- IRunningObjectTable Rot = null;
- GetRunningObjectTable(0, out Rot);
- if (Rot == null)
- return null;
- // Получаем перечислитель записей ROT
- IEnumMoniker monikerEnumerator = null;
- Rot.EnumRunning(out monikerEnumerator);
- if (monikerEnumerator == null)
- return null;
- monikerEnumerator.Reset();
- List<object> instances = new List<object>();
- IntPtr pNumFetched = new IntPtr();
- IMoniker[] monikers = new IMoniker[1];
- // Проходим по всем записям и идентифицируем экземпляры приложений
- while (monikerEnumerator.Next(1, monikers, pNumFetched) == 0)
- {
- IBindCtx bindCtx;
- CreateBindCtx(0, out bindCtx);
- if (bindCtx == null)
- continue;
- string displayName;
- monikers[0].GetDisplayName(bindCtx, null, out displayName);
- foreach (string clsId in clsIds)
- {
- if (displayName.ToUpper().IndexOf(clsId) > 0)
- {
- object ComObject;
- Rot.GetObject(monikers[0], out ComObject);
- if (ComObject == null)
- continue;
- instances.Add(ComObject);
- break;
- }
- }
- }
- return instances;
- }
- void TestROT()
- {
- // Ищем AutoCAD 2009 и 2010 и 2014
- string[] progIds =
- {
- "AutoCAD.Application.17.2",
- "AutoCAD.Application.18",
- "AutoCAD.Application.19.1"
- };
- List<object> instances = GetRunningInstances(progIds);
- foreach (object acadObj in instances)
- {
- try
- {
- // Выполняем запланированные действия с выбранным приложением ...
- }
- catch
- {
- }
- }
- }
Обсуждение: http://adn-cis.org/forum/index.php?topic=433
Опубликовано 08.01.2014