gpt4 book ai didi

com - 创建无 reg 的托管 COM 对象时,如何让 CLR 查看与主应用程序的可执行文件不同的目录?

转载 作者:行者123 更新时间:2023-12-01 04:00:48 26 4
gpt4 key购买 nike

这是一个复杂的问题,涉及与 COM、CLR 和无注册 COM 相关的一些神秘领域。

首先,我的主要应用程序是用 python 编写的。因此,它的代码库(开发中)位于 C:\mainapp\main.py。

当然,在windows上,执行程序的是C:\Python27\python.exe。

我现在想使用 python 中的无注册 COM(使用 win32com)与我控制的用 C# 编写的 COM 对象对话(使用 IDispatch),该对象位于 C:\mainapp\ManagedCOMObject.dll

注意:如果您不会说 python/pythoncom,请注意对 Dispatch() 的调用最终归结为 CoCreateInstance()。

尝试 1

#main.py:

import win32com.client
CLSID_ManagedComObject_MyClass = "{zzzzz....}" #This is correct
myclass = win32com.client.Dispatch(CLSID_ManagedComObject_MyClass)

结果

失败,因为对象不在注册表中(如预期的那样),而且我没有提到任何关于 list 文件的内容,python.exe 的 list 显然不知道我的对象。

尝试 2
#main.py:

ac = ActivationContext("C:\mainapp\myapp.manifest", asm_dir="C:\mainapp")
with ac.activate():
#The above two lines fill in a ACTCTX structure, call CreateActCtx, and call ActivateActCtx
import win32com.client
CLSID_ManagedComObject_MyClass = "{zzzzz....}" #This is correct
myclass = win32com.client.Dispatch(CLSID_ManagedComObject_MyClass)

-
#myapp.manifest:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32"
name="My.Main.App"
version="1.0.0.0"
processorArchitecture="x86"
/>
<dependency>
<dependentAssembly>
<assemblyIdentity
name="ManagedComObject"
version="1.0.0.0"
processorArchitecture="msil"
/>
</dependentAssembly>
</dependency>
</assembly>

请注意,ManagedCOMObject 有一个嵌入式 list ,它使用 clrClass 标记声明 COM 对象。

结果

ActicateActCtx 调用成功并正确解析了 myapp.manifest 和 ManagedComObject.dll 的 list - 我使用 sxstrace.exe 验证了这一点。

在探测 C:\Python27\ManagedComObject.dll 后,对 CoCreateInstance 的调用失败并出现 FileNotFound。融合日志声称 PrivatePath 未设置(推测是因为 python.exe.config 不存在),并且根本没有在 C:\mainapp 中查找 C# 对象。

问题
  • 为什么会失败?我相信这是因为 CLR COM 加载程序 stub 无法导入我的 C# 程序集。如果在这一步之前失败,CLR 甚至不会加载,所以它正在探测和创建融合日志这一事实让我相信这是因为 CLR 找不到 ManagedCOMObject.dll。
  • 请注意,CLR 已加载 - 我相信这意味着 COM 已成功查看当前激活上下文以找到注册。我不确切知道 clrClass 在 list 中做了什么,但大概它成功加载了 CLR。
  • 我现在假设问题是 CLR 在加载程序集时没有注意 ActCtx。如果我正在编写托管代码,我可以挂接到 AppDomain.CurrentDomain.AssemblyResolve 事件并自己找到 DLL。由于我正在编写非托管代码,并且仅隐式托管 CLR,我可以以某种方式更改我的应用程序 PrivatePath 和/或如何探测程序集吗?
  • 最佳答案

    I assume now that the issue is the CLR is not paying attention to the ActCtx when loading assemblies



    对,那是正确的。 CLR 有自己的策略来定位不受 Windows 激活上下文影响的程序集。默认情况下,它只在 GAC 中查找,然后在 EXE 的私有(private) bin 路径中查找。您可以使用 Fuslogvw.exe 实用程序看到这一点。

    你在这里没有很多很好的选择。在 GAC 中安装程序集是显而易见的解决方案,并且通常适用于 [ComVisible] 程序集,因为它有助于解决 COM DLL Hell 问题。您唯一可以做的是将其复制到 C:\Python27 目录或在同一目录中写入 python.exe.config 文件,将探测路径更改为 C:\Python27 的子目录。两者都不能很好地扩展。自己托管 CLR 或编写 AppDomain.AssemblyResolve 事件处理程序是不可能的。

    如果您想避免 Regasm.exe/codebase,使用 GAC 是合适的解决方案

    关于com - 创建无 reg 的托管 COM 对象时,如何让 CLR 查看与主应用程序的可执行文件不同的目录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13591131/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com