问题标签 [running-object-table]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - C#:从运行对象表中获取 COM 对象
我正在开发一个使用第三方 COM 服务器 API 的项目。COM 服务器是我无法控制的本地服务器(进程外 exe)。
我正在尝试从 runnin 对象表访问 COM 对象,以在从应用程序的每个实例开始的几个 COM 对象实例之间进行选择:
如果我启动目标应用程序的两个实例,ROT 转储会显示相应 COM 对象(此处命名为 IApplication)的两个实例,因为 GetDisplayName 显示在注册表中注册的接口 IApplication 的正确 clsid。
问题是我从 Rot.GetObject 获得的对象被描述为 System.__ComObject 并且不能强制转换为 IApplication(InvalidCastException,因为 QueryInterface 因 E_NOINTERFACE 失败),即使它们的绰号描述了正确的 clsid ...
我尝试将它以编程方式投射到我的项目中的每个可用类型,只是为了看看,但唯一的成功是将它投射到 System.__ComObject...
我也尝试使用 IMoniker.BindToObject 而不是 Rot.GetObject 但这次,当我提供相应的接口 GUID 时,我得到了 FileNotFound 异常。当我为 IUnknown 提供 riid 时,BindToObject 有效,但它给了我一个 System.__ComObject 我无法转换(回到第一方!)。
有关信息,在 ROT 转储中,我还可以显示与目标应用程序中打开的项目相对应的文件名字对象,但我也无法从中创建 COM 对象。
任何人都知道如何从 ROT 中正确检索对象?
感谢和问候。
编辑 :
几天后,对这个问题有了新的认识,我发现名字对象显示名称中的 CLSID 与我想要的不完全相同,但有两个数字(indexof 测试结果是错误的)。
仔细阅读 clsid 后发现,名字对象的显示名称中的 clsid 是 IApplication 的 coclass 的 clsid,而不是 IApplication 的 clsid。
我尝试将对象转换为“ApplicationClass”(前面提到的 coclass),但这给了我一个例外。我得到的附加信息(法语)可以翻译如下:不可能将 __ComObject 包装器实例转换为另一个类,但只要底层 com 组件支持接口 IID 的 QueryInterface 调用,就可以将这些实例转换为接口。
关于如何从这里开始的任何想法?
c# - C# 运行主动自动化对象 - 如何获取事件源?
我有一个(长期运行的)控制台应用程序,用 C# 编写,我希望能够通过 COM 操作它(所以没有 InProc DLL 和 regasm.exe)。IDispatch
是我所需要的 - 所以一个经典的 OLE 自动化对象。
在这里,我将展示我尝试做的最小版本。我已经定义了一个这样的 COM 类:
我只是在Main()
运行对象表 (ROT) 中使用"comTestApp"
Moniker 注册对象并休眠应用程序。你可以在这里看到完整的源代码。
当我尝试调用对象的方法时,这工作得很好。例如,这个 VBScript 工作正常:
但是当我尝试连接事件时:
调用时ConnectObject
出错(错误 0x80020009“无法连接对象”)。
如果我使用 regasm.exe 将程序集注册为 InProc 对象,则相同的代码(只需添加类 GUID/ProgID)可以工作,但我不需要。我需要访问正在运行的应用程序,这就是我使用 ROT 的原因。
我创建了一个简单的 C++ 测试,看看我是否能找到有关该问题的更多信息。来源在这里。我编写了一个最小的 COM 对象来实现IDispatch
应该充当事件接收器的接口。首先我从 ROT 中获取对象,查询IConnectionPointContainer
,然后获取IConnectionPoint
的ITestEvents
IID,最后调用它的Advise()
方法。与 VBScript 一样,它会失败(尽管我收到另一个错误 - 0x80040202)。我在事件接收器的方法上放置了一个断点,QueryInterface
以查看调用时会发生什么Advise()
。我可以看到它QueryInterface
被各种接口调用,最后它请求 my ITestEvents
,我返回并设置 status S_OK
。但是,该Advise()
方法仍然返回上述错误。
我还尝试了另一件事:我已将.的 IID设置ITestEvents
为的 GUID 。现在回来了!我什至模拟了一个事件,并且调用了事件接收器的方法!唉,这通常不能解决问题。如果您直接通过 IID 请求它 - 您会得到它,但它似乎没有被正确枚举,并且 VBScript 仍然无法正常工作。{00020400-0000-0000-C000-000000000046}
IDispatch
Advise()
S_OK
Invoke()
IConnectionPointContainer
ITypeInfo
我几乎没有使用 COM 的经验,所以我不知道从哪里开始。如果我使用IDispatch
IID 就可以工作,这让我想知道ITestEvents
接口是否需要一些自定义编组,尽管它是纯粹的IDispatch
,所以我认为它应该由运行时处理好。
谢谢!
c# - AllowAutoPlay 永远不会被调用
我有一个 WinForms 应用程序。就在 Program.cs 中创建实际表单之前,我实例化了一个Autoplay
类。注册成功,在强制性的第一个返回值 65536 之后,但我从来没有接到任何对AllowAutoPlay()
.
我错过了什么吗?
这是代码:
第二次调用的 cookie 很好、一致,但在 131073 或 0x00020001 处很好。
我使用了以下文章:Prevent Autoplay、65536 error和CodeProject。
断点或消息框均不显示。
我正在使用 Visual Studio 2017 在 Windows 10 上运行。
想法?
c# - 获取多个相同类型的正在运行的 COM 对象
我试图找到 Word 的第一个可见实例。我在这里找到了一些有用的代码并对其进行了轻微修改。
此代码的结果如下所示:
我希望对于一个实例 Visible 应该返回 true。似乎总是返回第一个实例。如果 word1 变为可见,则为所有实例返回 true。
c++ - 为什么 Windows 服务无法访问运行对象表
我有一个在后台运行的 Windows 服务,我想在某个时候告诉他从运行对象表中获取对象。
问题是,无论我尝试什么,似乎都无法实现。
它总是在 Windows API 的 GetObject 方法上失败,代码 0x800401E3(操作不可用)失败,就好像对象不存在一样。
在服务中失败的相同代码示例在常规可执行文件中运行良好,因此不太可能出现拼写错误或逻辑错误。
我尝试通过以下方式运行服务:
- 在本地系统帐户上
- 在管理员用户帐户上
- 在本地系统帐户上模拟管理员用户(使用 ImpersonateLoggedOnUser)
- 它们都以相同的方式失败(如上所述,在 GetObject 方法上)
所以我想知道关于运行对象表和 Windows 服务是否存在我不知道的限制(对于可能的安全问题?)。
好吧,如果它可以工作,我会错过什么?除了用户权限之外,是否还有其他东西可以篡改我的服务从运行对象表中查看/检索数据的能力?
c# - 以管理员身份运行时,如何让 IEnumMoniker.Next 返回名字对象?
多年来,此代码在实用程序中运行良好。我们最近更新了程序以强制执行 UAC,但我们发现此代码仅在不以管理员身份运行时才有效;当以管理员身份运行时,while 循环内的代码永远不会执行,但相同的代码在未提升运行时返回一个名字对象名称列表。
我已经在 2 台机器上试过了。其他人可以试试这个并确认此代码仅在不以管理员身份运行时返回名字对象列表。
是否有人对为什么 IEnumMoniker 在提升的进程中运行时不返回名字对象但在不以管理员身份运行时返回列表有任何想法?
c++ - 进程外 COM 对象动态版本控制
我正在使用由 myexe.exe 托管的进程外 COM 对象。托管 COM 对象的这些 exe 有多个版本。每个版本的接口和方法都可以略有改变。每个 myexe.exe 文件都位于版本化文件夹中(例如 C:\v2\myexe.exe、c:\v3\myexe.exe)
无法提前知道哪个版本将运行。我的客户端应用程序使用 ROT 附加到正在运行的 exe。我需要能够动态使用该 COM 对象版本,通过 IUnknown.QueryInterface 发现接口。
不幸的是,如果在 Windows 注册表中注册了旧版本的 COM,我在使用新方法时会崩溃。一旦我使用“myexe.exe -regserver”在 Windows 注册表中注册了较新版本的进程外 COM,崩溃就会消失。所以我不能在运行时动态使用旧版本或新版本的 meexe.exe,因为每次我需要重新注册我的 com 版本。
关于我为什么会崩溃或如何解决问题的任何想法?
c# - 如何让我的 Windows 服务查看 ROT 中的对象?
编辑:虽然切线相关,但标记的“重复”并不是这个问题的真正重复,更重要的是不回答这个问题(因为问题不同)。我正在使用 Window 服务,而不是独立的用户空间应用程序。
这是我正在使用的内容:
我用 C# 编写了一个 Windows 服务(在 Windows Server 2019 中运行),它通过 COM 与其他软件交互。这个其他软件不是我可以访问源代码的软件,所以我不能更改 COM 注册标志或类似的东西,但它确实注册了自己并有一个 API。
我想使用我的服务中的运行对象表 (ROT) 通过名字对象显示名称获取其他软件的实例,但是从我的服务的角度来看,ROT 始终是空的,即使在服务本身启动一个实例之后也是如此其他软件通过 Process.Start() 返回一个有效的 PID。需要明确的是,这可以在独立的 Windows 控制台或 Windows 窗体应用程序中正常运行,但不能作为服务运行。
该服务被配置为作为该计算机上管理员组中的用户登录。为什么即使在启动进程本身之后,它也看不到 ROT 中的任何内容?
这是一个示例代码片段。在控制台应用程序中运行时,它会计算许多名字对象,在我的服务中运行时,计数器始终为 0,即使在它启动进程之后也是如此。
提前致谢。
c# - 使用 Activator.CreateInstance() 创建时未释放 Inventor COM 对象
我的问题是:如果 Autodesk Inventor 没有运行,我的应用程序(控制台应用程序)会创建一个新实例Activator.CreateInstance(InventorType);
并将其用作 COM 对象。当我的应用程序没有退出 Inventor 而是让它保持打开状态并且用户稍后手动退出它时,TaskManager 中仍然有一个进程inventor.exe正在运行,它只能在 TaskManager 中被杀死。奇怪的是,只有将这两件事结合起来时,才会出现问题。每当我的应用程序退出 Inventor 并InventorApp.Quit();
正确关闭并且没有任何进程处于打开状态时。
如果我的应用程序使用 Inventor 启动Process.Start(..);
或用户在启动应用程序之前启动 Inventor,然后我的应用程序使用 Inventor 抓取,Marshal.GetActiveObject(ProgId);
则无论应用程序或用户退出 Inventor 都没有问题。
如果我的应用程序使用 Inventor 启动Activator.CreateInstance(InventorType);
然后保持 Inventor 打开,应用程序关闭然后重新启动,它使用 Inventor 抓取Marshal.GetActiveObject(..);
然后退出 Inventor,InventorApp.Quit();
没有问题。
所以,左开进程的问题只出现在这个特定的组合中:
- 通过以下方式启动 Inventor
Activator.CreateInstance(InventorType);
- 用户手动退出 Inventor
左打开进程不再在运行对象表中,因此它不能再作为 COM 对象处理,并且它没有可见的 UI,这意味着它只能在 TaskManager 中被杀死。
使用所描述的“错误组合”,我什至尝试以GC.WaitForPendingFinalizers(); GC.Collect();
不同的组合以及 before 和/或 after 多次调用(我知道这很糟糕,但我只是在尝试一切)Marshal.ReleaseComObject(invApp); Marshal.FinalReleaseComObject(invApp);
。我什至尝试了一个最小的应用程序,它实际上什么都不做。请参阅下面的代码。
那么,是Activator.CreateInstance(InventorType);
什么导致了这种情况?有什么办法可以防止这种情况发生吗?或者这是 Inventor 特有的问题?
最小的应用程序示例: