EB.*_*EB. 5 com clr .net-assembly activation-context-api
这是一个复杂的问题,涉及与 COM、CLR 和无 reg-free COM 相关的一些神秘领域。
首先,我的主要应用程序是用 python 编写的。因此,它的代码库(开发中)位于 C:\mainapp\main.py。
当然,在windows上,执行程序的是C:\Python27\python.exe。
我现在想使用 python 中的 reg-free COM(使用 win32com)与我控制的用 C# 编写的 COM 对象交谈(使用 IDispatch),该对象位于 C:\mainapp\ManagedCOMObject.dll
注意:如果您不会说 python / pythoncom,请注意对 Dispatch() 的调用最终归结为 CoCreateInstance()。
#main.py:
import win32com.client
CLSID_ManagedComObject_MyClass = "{zzzzz....}" #This is correct
myclass = win32com.client.Dispatch(CLSID_ManagedComObject_MyClass)
Run Code Online (Sandbox Code Playgroud)
失败,因为对象不在注册表中(正如预期的那样),而且我没有提到任何关于清单文件的内容,而且 python.exe 的清单显然不知道我的对象。
#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)
Run Code Online (Sandbox Code Playgroud)
——
#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>
Run Code Online (Sandbox Code Playgroud)
请注意,ManagedCOMObject 有一个嵌入式清单,它使用 clrClass 标记声明 COM 对象。
ActicateActCtx 调用成功并正确解析 myapp.manifest 和 ManagedComObject.dll 的清单 - 我使用 sxstrace.exe 验证了这一点。
在探测 C:\Python27\ManagedComObject.dll 后,调用 CoCreateInstance 失败并显示 FileNotFound。融合日志声称未设置 PrivatePath(可能是因为 python.exe.config 不存在),并且根本没有在 C:\mainapp 中查找 C# 对象。
为什么这会失败?我相信这是因为 CLR COM 加载程序存根无法导入我的 C# 程序集。如果在这一步之前失败,CLR 甚至不会加载,所以它正在探测和创建融合日志这一事实让我相信这是因为 CLR 找不到 ManagedCOMObject.dll。
请注意,CLR 已加载 - 我相信这意味着 COM 已成功查看当前激活上下文以找到注册。我不知道 clrClass 在清单中做了什么,但大概它成功加载了 CLR。
我现在假设问题是 CLR 在加载程序集时没有注意 ActCtx。如果我正在编写托管代码,我可以连接到 AppDomain.CurrentDomain.AssemblyResolve 事件并自己找到 DLL。由于我正在编写非托管代码,并且仅隐式地托管 CLR,我可以以某种方式更改我的应用程序 PrivatePath 和/或程序集的探测方式吗?
我现在假设问题是 CLR 在加载程序集时没有关注 ActCtx
对,那是正确的。CLR 有自己的策略来定位不受 Windows 激活上下文影响的程序集。默认情况下,它仅在 GAC 中查找,然后在 EXE 的专用 bin 路径中查找。您可以使用 Fuslogvw.exe 实用程序来查看这一点。
这里没有太多好的选择。在 GAC 中安装程序集是显而易见的解决方案,通常适用于 [ComVisible] 程序集,因为它有助于解决 COM DLL Hell 问题。您唯一能做的就是将其复制到 C:\Python27 目录或在同一目录中写入 python.exe.config 文件,将探测路径更改为 C:\Python27 的子目录。两者的扩展性都不好。自行托管 CLR 或编写 AppDomain.AssemblyResolve 事件处理程序是不可能的。
如果您想避免 Regasm.exe /codebase,使用 GAC 是合适的解决方案
| 归档时间: |
|
| 查看次数: |
996 次 |
| 最近记录: |