You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从C#外部程序访问指定的Bentley MicroStation V8i实例?

问题描述

我有一个通过API访问MicroStation(V8i)的C#应用程序,当前遇到以下问题:

  • 同时打开多个MicroStation实例时,仅能访问第一个启动的实例
  • 尝试用AutoCAD场景下的《Accessing COM applications from the Running Object Table》方案解决,但无效
  • 使用MicroStationDGN.ApplicationObjectConnector筛选运行对象表(ROT)时,返回的IMoniker数量与实例数一致,但所有对象引用都指向同一个实例(类似单例)
  • 测试代码如下:
string progId = "MicroStationDGN.ApplicationObjectConnector";

List<object> instances = GetRunningInstances(progId);
bool theSame = instances[0] == instances[1];    // 当存在至少2个实例时,返回true

请问是否有方法可以访问已打开的MicroStation实例中的指定实例?

解决方案

针对MicroStation V8i的COM访问特性,你可以通过以下方式区分并访问指定实例:

1. 通过进程ID关联实例

MicroStation每个实例对应独立的ustation.exe进程,你可以通过COM对象的ProcessID属性获取关联进程ID,再与系统进程匹配:

using System.Diagnostics;
using Bentley.MicroStation.InteropServices;

// 获取所有MicroStation进程
var msProcesses = Process.GetProcessesByName("ustation");

// 从ROT获取所有ApplicationObjectConnector实例
string progId = "MicroStationDGN.ApplicationObjectConnector";
List<object> instances = GetRunningInstances(progId);

// 遍历实例,匹配进程ID区分目标实例
foreach (var instance in instances)
{
    var app = instance as Application;
    if (app != null)
    {
        int processId = app.ProcessID;
        var targetProcess = msProcesses.FirstOrDefault(p => p.Id == processId);
        if (targetProcess != null)
        {
            // 可通过窗口标题、启动时间进一步筛选
            Console.WriteLine($"实例进程ID: {processId}, 窗口标题: {targetProcess.MainWindowTitle}");
            // 找到目标实例后执行操作
            // app.MessageBox("已定位到目标实例");
        }
    }
}

2. 通过打开的设计文件路径区分

每个MicroStation实例通常对应不同的DGN文件,你可以通过ActiveDesignFile属性获取文件路径,以此识别目标实例:

using Bentley.MicroStation.InteropServices;

string targetDgnPath = @"C:\Projects\TargetDesign.dgn";
string progId = "MicroStationDGN.ApplicationObjectConnector";
List<object> instances = GetRunningInstances(progId);

Application targetInstance = null;
foreach (var instance in instances)
{
    var app = instance as Application;
    if (app != null && app.ActiveDesignFile.FullName.Equals(targetDgnPath, StringComparison.OrdinalIgnoreCase))
    {
        targetInstance = app;
        break;
    }
}

if (targetInstance != null)
{
    // 对目标实例执行操作
    targetInstance.MessageBox("已找到目标实例");
}

3. 修正ROT实例的获取逻辑

原GetRunningInstances方法可能未正确解析IMoniker的唯一标识,你可以修改方法读取DisplayName来区分实例:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

public static List<object> GetRunningInstances(string progId)
{
    List<object> instances = new List<object>();
    IRunningObjectTable rot = null;
    IEnumMoniker enumMoniker = null;

    try
    {
        GetRunningObjectTable(0, out rot);
        rot.EnumRunning(out enumMoniker);
        enumMoniker.Reset();

        IMoniker[] moniker = new IMoniker[1];
        int fetched;

        while (enumMoniker.Next(1, moniker, out fetched) == 0 && fetched == 1)
        {
            IBindCtx bindCtx = null;
            CreateBindCtx(0, out bindCtx);

            string displayName;
            moniker[0].GetDisplayName(bindCtx, null, out displayName);

            if (displayName.Contains(progId))
            {
                object instance;
                rot.GetObject(moniker[0], out instance);
                instances.Add(instance);
            }

            Marshal.ReleaseComObject(bindCtx);
            Marshal.ReleaseComObject(moniker[0]);
        }
    }
    finally
    {
        if (enumMoniker != null) Marshal.ReleaseComObject(enumMoniker);
        if (rot != null) Marshal.ReleaseComObject(rot);
    }

    return instances;
}

// 导入COM交互所需API
[DllImport("ole32.dll")]
private static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);

[DllImport("ole32.dll")]
private static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);
说明

MicroStation V8i的ApplicationObjectConnector设计上可能返回共享代理对象,但通过获取实例的进程ID或关联文件路径,即可精准区分并访问指定实例。

内容的提问来源于stack exchange,提问作者Marek Praski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 23:11:12