在 VB.Net 中获取 COM 对象的特定实例

2024-03-15

我正在 .Net 中编写一个 Windows 窗体应用程序,以列出第三方 CAD/CAM 软件(在本例中为 CATIA)的所有正在运行的实例,并让用户选择其中一个来执行几个自动化任务。为了执行自动化任务,我需要获取 COM 对象的特定实例 - 与 Getobject() 相比,它为我提供了非特定的 COM 实例。有没有办法使用窗口句柄或任何其他方法获取特定的 COM 实例?

更新: 正如 Raymond 所说,没有适用于所有 COM 对象的单一解决方案;但是我设法使用以下代码获取 CATIA COM 对象(其中使用 ROT 用所有 CATIA COM 实例名称填充列表):

<DllImport("user32.dll", CharSet:=CharSet.Auto)> Private Shared Sub GetClassName(ByVal hWnd As System.IntPtr, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) End Sub
<DllImport("ole32.dll", ExactSpelling:=True, PreserveSig:=False)> Private Shared Function GetRunningObjectTable(ByVal reserved As Int32) As IRunningObjectTable End Function
<DllImport("ole32.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True,  PreserveSig:=False)> Private Shared Function CreateItemMoniker(ByVal lpszDelim As String, ByVal lpszItem As String) As IMoniker End Function
<DllImport("ole32.dll", ExactSpelling:=True, PreserveSig:=False)> Private Shared Function CreateBindCtx(ByVal reserved As Integer) As IBindCtx End Function

Try

    Dim ROTObject As Object = Nothing
    Dim runningObjectTable As IRunningObjectTable
    Dim monikerEnumerator As IEnumMoniker = Nothing
    Dim monikers(1) As IMoniker

    runningObjectTable = GetRunningObjectTable(0)
    runningObjectTable.EnumRunning(monikerEnumerator)
    monikerEnumerator.Reset()

    Dim numFetched As IntPtr = New IntPtr()
    While (monikerEnumerator.Next(1, monikers, numFetched) = 0)
        Dim ctx As IBindCtx
        ctx = CreateBindCtx(0)

        Dim runningObjectName As String = ""
        monikers(0).GetDisplayName(ctx, Nothing, runningObjectName)

        runningObjectName = runningObjectName.ToUpper
        If (Not runningObjectName.Equals("")) Then
            Dim runningObjectIns As Object = Nothing
            runningObjectTable.GetObject(monikers(0), runningObjectIns)

            'Check if object is a Catia object
            Try
                Dim catiaIns As INFITF.Application = Nothing
                catiaIns = DirectCast(runningObjectIns, INFITF.Application)
                ListCATIA.Items.Add(catiaIns.Windows.Count)
             Catch Exc As Exception
                MessageBox.Show(Exc.ToString())
            End Try
        End If
    End While

Catch Exc As Exception
    Throw Exc
End Try

但是,所有 CATIA 实例均指加载的第一个 CATIA 应用程序。不知道为什么,有人吗?


您的代码中的“问题”是调用GetObject always返回在运行对象表 (ROT) 中找到的第一个活动服务器。枚举 ROT 不会改变该行为,而且有点令人沮丧,因为它确实表明 ROT 中有多于一台服务器。请注意,枚举中返回的某些项目可能实际上并未运行:GetObject返回第一个active服务器——不一定是枚举返回的第一个服务器。

然而,对于 CATIA,尤其是is可能获得特定的实例。我怀疑如果您可以获得感兴趣的特定实例来按需运行一些代码,那么许多应用程序都是可能的,before您实际上获得了一个指向 COM 实例的指针。

对于 CATIA,这是我使用的流程的粗略概述:


1. Make a dll with two functions:
    HRESULT __stdcall CoMarshalToFile(IUnknown* punk, const char* const filePath)
    /* uses `::CreateStreamOnHGlobal`, `::CoMarshalInterface`, `::CoGetMarshalSizeMax`,
     and `::GetHGlobalFromStream` to marshal the IUnknown to the specified file.
    */
    HRESULT __stdcall CoMarshalFromFile(IUnknown** ppunk, const char* const filePath)
    /* uses `::CreateStreamOnHGlobal` and `::CoUnmarshalInterface` to marshal
     from the file to an IUnknown pointer.
    */

2. In CATIA:
  Note: this only needs to be done on the development computer.
  Make a new "VBA projects" macro library. 
    Add "declare" statements for:
        "LoadLibrary" (Windows API)
        "CoMarshalToFile" (DLL specified above)
    Add a function 
        Public Function MarshalCatiaToFile _
            (marshalInstanceFilePath As String, _
                marshalDllFolder As String) As Long

    MarshalCatiaToFile calls "LoadLibrary" to load the C++ DLL
    and then calls CoMarshalToFile (in DLL) to marshal the CATIA instance
    to a file.

  Remove the macro library from CATIA's list of macro libraries.

3. Create a file:
    "C:\Temp\CatiaOnTheFlyCatScripts\OnTheFlyCatScript.catvbs"
  The file can be empty.

4. In CATIA:
      Note: this must be done for *each* user of CATIA on *each* computer used.
      It may be possible to make this available to all users without individual
      setup required: it is saved in "FrameUserAliases.CATSettings"
      It may also be possible to reverse engineer the settings file and set up
      the needed data from outside CATIA.

    Add "C:\Temp\CatiaOnTheFlyCatScripts\" as a new "Directories" macro library.
    Make the added library "current"
    Use "Tools --> Customize --> Commands --> Macros" to assign a
      "User Alias:" to the "OnTheFlyCatScript.catvbs" script file.
      Name the alias "ExecuteOnTheFlyCatScript".
    Remove the macro library from CATIA's list of macro libraries.
    Close CATIA at this point to force the changes to be saved.

5. VB.net / C# program:
      Add the DLL (from step 1) and the CatVBA macro library (from step 2) as
      "Embedded Resource" to the project. 

      During program execution:
        Extract the DLL and macro library to an appropriate location. 
        Load the DLL into session using "LoadLibrary".
        Create the file:
          "C:\Temp\CatiaOnTheFlyCatScripts\OnTheFlyCatScript.catvbs"

        The "OnTheFlyCatScript.catvbs" will be executed in CATIA. It
          uses CATIA.SystemService.ExecuteScript to execute the 
          "MarshalCatiaToFile" function in the CatVBA macro library.
          Add method of choice to this file to indicate success/failure.
          I use a dialog box with the appropriate title.

        To execute the "OnTheFlyCatScript.catvbs":
          Using the Windows API functions, get the window handle for the
            "Power Input" box at the bottom right of the "desired" 
            CATIA window.
          Using the Windows API functions (*NOT* "SendKeys") send 
            "c:ExecuteOnTheFlyCatScript" + {Enter} to the "Power Input".
          Wait for the "completion" signal from the script. If you used
            a dialog box, use the Windows API function to close it.

        Assuming the script succeeded in marshaling the CATIA instance to
          a file, call the DLL function CoMarshalFromFile to get the CATIA
          instance.
 

虽然需要处理许多“移动”部件,但它确实允许您“同时”自动执行多个 CATIA 会话。非常适合我的目的:从一组 CATIA 模型中自动提取数据,并一次使用多个 CATIA 会话自动创建一组 CATIA 模型。我的应用程序的瓶颈是单个 CATIA 会话,而不是 CPU 资源(每个处理器机器使用双处理器 4 或 6 核);添加更多会话可以提高吞吐量。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 VB.Net 中获取 COM 对象的特定实例 的相关文章

随机推荐

  • 无法让简单的引导模式工作

    我正在尝试让一个简单的引导程序模态示例正常工作 我遵循这个文件 http igotstamp appspot com pages javascript上面写着 您可以轻松激活页面上的模态 而无需编写一行 JavaScript 只需为元素提供
  • Visual Studio 展开/折叠键盘快捷键[重复]

    这个问题在这里已经有答案了 In Visual Studio if I have a code file open I can press CTRL M or CTRL M O to collapse all code blocks reg
  • 为什么这个类有两个构造函数?

    我在旨在说明构造函数的幻灯片中看到了这一点 我现在很困惑 因为它有两个具有相同工作的构造函数 接受在第二个构造函数中将 gpa 设置为零 为什么编码器需要重复this id id this name name 再次 为什么这个类需要两个构造
  • 来自 Python 的 AWS 网络负载均衡器后面的客户端 IP

    当在网络负载均衡器后面运行套接字服务器时 实例由 IP 指定 server sock socket socket family socket AF INET type socket SOCK STREAM proto socket IPPR
  • InvalidArgumentError:索引[0,0] = -1 不在 [0, 10) 中

    它与 MLP 一起进行二元分类效果很好 然而 在 LSTM 和卷积中 它给出了InvalidArgumentError 我发现 y 需要重塑 我就这么做了 我尝试了 x 的所有正值 并且模型运行良好 那么负值有什么问题呢 数据在代码中给出
  • Android 应用程序使用 android.permission.READ_LOGS - 这是不礼貌的吗?

    我有一个可以从 Android Market 获取的应用程序 一些用户要求在事情没有按预期进行时进行调试 我一直在考虑添加一个菜单项来显示输出 Process mLogcatProc null BufferedReader reader n
  • Dagger2:用组件本身注入模块提供的实现类

    考虑到模块都是通过 Dagger1 规范相互共享的complete false library true 您可以收到由 Provides通过构造函数参数的方法 就像这样 public class GetUserForUsernameTask
  • 如何计算列表中项目的出现次数

    我是 Dart 新手 目前我有一个重复项目列表 我想计算它们的出现次数并将其存储在地图中 var elements a b c d e a b c f g h h h e a 我想要得到这样的结果 a 3 b 2 c 2 d 2 e 2 f
  • 格式 - 帮助打印表格

    这个问题可能会以捂脸结束 但我已经尝试了一段时间 尽管阅读了超规范 但仍然卡住了 基本上我想做的是 format t 5d 1 23 2 312 23 456 1 7890 但不应该对 5 进行硬编码 而是应该从列表中计算 任何嵌套列表中最
  • 从 ANDROID 2.2 发送 UDP 包(HTC 希望)

    我有一个局域网 我想从我的 android htcdesire 发送一条 udp 消息到我的电脑 它们之间有一个 WLAN 路由器 问题是 UPD 消息永远不会到达 PC Android上的代码 package org example an
  • JSON 架构允许日期或空字符串

    我需要定义一个 JSON 模式 其中输入可以是日期或空字符串 我当前的 JSON 架构是 type object required FirstName DateOfBirth properties FirstName type string
  • R - 自动调整 Excel 列宽

    如何使用自动调整列宽openxlsx 我的其中一列有一个日期变量 例如21 08 2017 并且如果使用复制ctrl c从 Excel 中 并正常粘贴到其他地方 它显示为 如果增加列宽以显示 Excel 中的内容 则可以正常粘贴 我想将重复
  • 在 d3 中设置 id 问题

    这就是我正在做的 selection canvas selectAll circle data mydata selection enter append circle selection attr id function d i var
  • Scala - Slick - 获取包装选项的 TypedType[T]

    通常创建这样的自定义 ID case class CustomID value Int extends MappedTo Int 并用 Option CustomID 等类型表示可为 null 的自定义 ID 但是 我希望能够将 Optio
  • 为什么 >= 有效但 => 无效?

    当检查一个整数是否等于或大于当前数字时 所以我输入 if 5 gt 6 Bla 但它显示这是一个错误 为什么 这不是完全一样吗 if 5 gt 6 Bla 它不起作用的原因是因为 gt 不等于 gt gt 用于拉姆达表达式 http msd
  • Nil 和 List 作为 Scala 中的 case 表达式

    此代码编译 def wtf arg Any arg match case Nil gt Nil was passed to arg case List gt List was passed to arg case gt otherwise
  • Java - split(regex, limit) 方法实际上如何工作? [复制]

    这个问题在这里已经有答案了 我试图了解 split 方法的工作原理 但对此有些困惑 在 oracle 文档页面给出的这个示例中 String str boo and foo String str1 str split o 2 Output
  • 如何在 AWS Lambda 函数中获取 AWS API Gateway 调用 URL?

    我正在将代理集成与 Java lambda 函数结合使用 lambda 处理程序的输入是一个表示传入请求的 JSON 对象 它有正文 标头 查询参数等 但它不包括 API 网关解析的正文的源 URL 查询参数等 有没有办法获取它 问题是 A
  • 姜戈树胡子 AL、NS、MP 之间有什么区别

    我正在尝试制作一个模型来对某些对象进行分类 我已经尝试使用 django mptt 轻松检索相关类别 现在我正在搜索不同的解决方案以找到最好的解决方案 我无法找出物化路径 邻接列表和嵌套集之间的主要区别 维基百科没有给我一个简短的答案 我所
  • 在 VB.Net 中获取 COM 对象的特定实例

    我正在 Net 中编写一个 Windows 窗体应用程序 以列出第三方 CAD CAM 软件 在本例中为 CATIA 的所有正在运行的实例 并让用户选择其中一个来执行几个自动化任务 为了执行自动化任务 我需要获取 COM 对象的特定实例 与