我注意到,如果我有一个.NET Framework4.8程序集,该程序集公开了一个接受System.Collections.ArrayList
参数的COM互操作方法,然后从VB6调用该方法,则.NET方法将获得ArrayList
的副本,而不是传递的原始ArrayList
:GetHashCode()
在VB6对象上返回不同的值,而不是在.NET对象上返回不同的值;如果.NET方法修改ArrayList
,则不会对VB6侧的对象进行修改。
但是,如果在.exe.config文件中添加了一个<startup useLegacyV2RuntimeActivationPolicy="true">
部分,它将按预期的方式工作:GetHashCode()
在VB6和.NET边返回相同的值,而.NET方法所做的修改在VB6端看到。
这一切为什么要发生?有什么方法可以让它在不设置useLegacyV2RuntimeActivationPolicy="true"
的情况下按我预期的方式工作吗?(我不介意把它设置为真,我主要好奇为什么要这样做才能奏效)
详细信息:
我在.NET端使用了这个选项,并在项目构建配置上检查了“”。
using System.Collections;
using System.Runtime.InteropServices;
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class ItemAdder
{
public int AddItem(ArrayList ar)
{
ar.Add("def");
return ar.GetHashCode();
}
}
在VB6端,创建项目,向C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb
添加一个项目引用,并将其放入模块中:
Option Explicit
Sub Main()
Dim al As New ArrayList
Dim adder As New ItemAdder
Dim msg As String
al.Add "abc"
msg = "HashCode in VB6 is: " & al.GetHashCode() & vbCrLf
msg = msg & "HashCode in .NET is: " & adder.AddItem(al) & vbCrLf
msg = msg & "Item was " & IIf(al.Count <= 1, "not ", "") & "added"
MsgBox msg
End Sub
.exe.config文件(如果从VB6 IDE运行,或者如果将VB6项目编译为EXE,则可以将其用作EXE的.config文件):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>
如果是useLegacyV2RuntimeActivationPolicy="true"
,则MsgBox将两个HashCodes显示为相等,并显示添加了该项。如果是useLegacyV2RuntimeActivationPolicy="false"
,则MsgBox显示不同的HashCodes,并且没有添加该项。
发布于 2022-09-30 06:51:11
这是因为从COM的角度来看,ArrayList是建立在.NET框架的旧版本之上的。
ArrayList COM注册为64位,在mscorlib.dll中构建在.NET框架2上:
ArrayList COM在32位(64位系统上)注册,在mscorlib.dll中基于.NET框架1:
因此,如果您使用.dll框架4构建.NET,并从VB6 (32位)调用它,您将在同一个过程中混合不同版本(这里的版本为4和1),这会产生问题。
如元素上的正式文档所述
如果应用程序使用遗留激活路径..。您希望这些路径激活CLR的版本4,而不是更早的版本,或者如果您的应用程序是用.NET框架4构建的,但是依赖于使用.NET框架的早期版本构建的混合模式程序集,那么仅在支持的运行时列表中指定.NET Framework4是不够的。此外,在配置文件中的元素中,必须将
useLegacyV2RuntimeActivationPolicy
属性设置为true
。..。
这基本上是一个“魔术”开关,如下所述:useLegacyV2RuntimeActivationPolicy是干什么用的?
useLegacyV2RuntimeActivationPolicy
属性基本上允许您说:“我对遗留的shim有一些依赖关系。请让他们按照他们以前选择的运行时的方式工作。
也来自同一链接:
最终,这个属性与“遗留的shim”的行为有关。您可以认为这些包含了几类CLR激活: ..。 Pre-v4com激活-这包括CoCreateInstance的CLSID (或类型标识符),其最新的注册是针对的前v4运行时版本。注意,这包括托管代码中的这种co类上的“新”操作符,或者Activator.CreateInstance对Type.GetTypeFromCLSID在这样一个CLSID上创建的类型的结果。 前v4 IJW (混合模式)激活??例如,在这样的程序集上调用本机导出。 本机运行时的本机激活--提供的COM CLSID --例如ICLRRuntimeHost的CLSID上的CoCreateInstance 托管框架CLSID的原生激活--比如System.ArrayList的CLSID (非常罕见的) CoCreateInstance
https://stackoverflow.com/questions/73902133
复制相似问题