从并排程序集创建 COM class 时出错 COR_E_NEWER_RUNTIME
Error COR_E_NEWER_RUNTIME when creating COM class from side by side assembly
我有以下情况:
- 本机 Delphi 应用程序应从 C# DLL 调用 COM 接口
- 我想在不注册 C# DLL 的情况下(并排)合作应用程序和 DLL
Delphi 应用程序代码(控制台可执行文件):
program TestSideBySide2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
mscorlib_TLB in 'mscorlib_TLB.pas',
TestSideBySide2_TLB in 'TestSideBySide2_TLB.pas';
var
sideBySide : TestSideBySide2_TLB._SideBySideClass;
intfSideBySide : TestSideBySide2_TLB.ISideBySideClass;
res : HRESULT;
begin
try
sideBySide := TestSideBySide2_TLB.CoSideBySideClass.Create();
res := sideBySide.QueryInterface(IID_ISideBySideClass,intfSideBySide);
Writeln(intfSideBySide.Version());
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
导入的 'TestSideBySide2_TLB.pas'
是使用 TLIBIMP.exe
工具从 DLL 生成的。
这是将作为资源链接到 Delphi 应用程序的应用程序清单:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity
type="win32"
name="TestSideBySide.exe"
version = "1.0.0.0" />
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="TestSideBySide2"
version="1.0.0.0" />
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="asInvoker"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
C# DLL代码(使用SharpDevelop编译)
using System;
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: Guid("07F9C367-BFA4-45AD-8A60-689096BD7AA9")]
namespace TestSideBySide2
{
/// <summary>
/// Exposed interface.
/// </summary>
[Guid("49D49031-12D8-40B5-85FA-B42133FD7DD0")]
public interface ISideBySideClass
{
string Version();
}
/// <summary>
/// Implementation of exposed interface.
/// </summary>
[Guid("A0BDB20B-A6E4-4A36-A64C-CC9186DD1C3E")]
public class SideBySideClass : ISideBySideClass
{
public string Version()
{
return "1.0.0-C#";
}
}
}
和程序集清单(也作为资源链接到 DLL 中):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="TestSideBySide2"
version="1.0.0.0" />
<clrClass
clsid="{A0BDB20B-A6E4-4A36-A64C-CC9186DD1C3E}"
progid="TestSideBySide2"
threadingModel="Both"
name="TestSideBySide2.SideBySideClass" >
</clrClass>
</assembly>
到目前为止一切都相当简单。 Delphi 应用程序可以解析绑定并加载 DLL。但是行
sideBySide := TestSideBySide2_TLB.CoSideBySideClass.Create();
失败,异常
EOleSysError: OLE-Error 8013101B, ClassID: {A0BDB20B-A6E4-4A36-A64C-CC9186DD1C3E}
错误代码解析为 COR_E_NEWER_RUNTIME
。
我检查了构建 DLL 的 .NET 运行时版本,这是 .NET 4.0(在我的 Windows 10 环境中可用)。
然后我尝试为较旧的运行时版本(2.0、3.0、3.5)构建 DLL,并且对于它们中的每一个都工作得很好。
当然,我一直在研究可能是什么问题,这是我到目前为止发现的有望解决问题(但没有解决)的内容:
- Cannot get to work VB.NET DLL referenced by VB6 client in reg-free scenario
- How to: Configure .NET Framework-Based COM Components for Registration-Free Activation(具体使用 DLL 清单
clrClass
元素中的 runtimeVersion="v1.4"
属性)
目前我不知道还能做什么。我在 Internet 上找到的任何其他资源仅指向我在上面列出的建议之一。
我还能忽略什么?
更新:
一位同事提到这可能是一个 Delphi 奇怪的问题,并且是从非托管代码调用的。
我们正在使用 Embarcadero Seattle Delphi 10.
我在此处找到的信息的帮助下解决了问题:
Runtime Versions and Errors 0x80131700 and 0x8013101b
我已经尝试在 DLL 的程序集清单中添加 .NET CLR 版本。这可以根据 clrClass
部分中的 class 来完成。
我不知道的是,runtimeVersion
属性必须是完全限定的。
完整的 clrClass
部分现在如下所示:
<clrClass
clsid="{A0BDB20B-A6E4-4A36-A64C-CC9186DD1C3E}"
progid="TestSideBySide2"
threadingModel="Both"
name="TestSideBySide2.SideBySideClass"
runtimeVersion="v4.0.30319">
</clrClass>
根据上面链接的文档,其他 CLR 版本的版本条目应该是:
- v1.0.3705
- v1.1.4322
- v2.0.50727
- v4.0.30319
我有以下情况:
- 本机 Delphi 应用程序应从 C# DLL 调用 COM 接口
- 我想在不注册 C# DLL 的情况下(并排)合作应用程序和 DLL
Delphi 应用程序代码(控制台可执行文件):
program TestSideBySide2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
mscorlib_TLB in 'mscorlib_TLB.pas',
TestSideBySide2_TLB in 'TestSideBySide2_TLB.pas';
var
sideBySide : TestSideBySide2_TLB._SideBySideClass;
intfSideBySide : TestSideBySide2_TLB.ISideBySideClass;
res : HRESULT;
begin
try
sideBySide := TestSideBySide2_TLB.CoSideBySideClass.Create();
res := sideBySide.QueryInterface(IID_ISideBySideClass,intfSideBySide);
Writeln(intfSideBySide.Version());
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
导入的 'TestSideBySide2_TLB.pas'
是使用 TLIBIMP.exe
工具从 DLL 生成的。
这是将作为资源链接到 Delphi 应用程序的应用程序清单:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity
type="win32"
name="TestSideBySide.exe"
version = "1.0.0.0" />
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="TestSideBySide2"
version="1.0.0.0" />
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="asInvoker"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
C# DLL代码(使用SharpDevelop编译)
using System;
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: Guid("07F9C367-BFA4-45AD-8A60-689096BD7AA9")]
namespace TestSideBySide2
{
/// <summary>
/// Exposed interface.
/// </summary>
[Guid("49D49031-12D8-40B5-85FA-B42133FD7DD0")]
public interface ISideBySideClass
{
string Version();
}
/// <summary>
/// Implementation of exposed interface.
/// </summary>
[Guid("A0BDB20B-A6E4-4A36-A64C-CC9186DD1C3E")]
public class SideBySideClass : ISideBySideClass
{
public string Version()
{
return "1.0.0-C#";
}
}
}
和程序集清单(也作为资源链接到 DLL 中):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="TestSideBySide2"
version="1.0.0.0" />
<clrClass
clsid="{A0BDB20B-A6E4-4A36-A64C-CC9186DD1C3E}"
progid="TestSideBySide2"
threadingModel="Both"
name="TestSideBySide2.SideBySideClass" >
</clrClass>
</assembly>
到目前为止一切都相当简单。 Delphi 应用程序可以解析绑定并加载 DLL。但是行
sideBySide := TestSideBySide2_TLB.CoSideBySideClass.Create();
失败,异常
EOleSysError: OLE-Error 8013101B, ClassID: {A0BDB20B-A6E4-4A36-A64C-CC9186DD1C3E}
错误代码解析为 COR_E_NEWER_RUNTIME
。
我检查了构建 DLL 的 .NET 运行时版本,这是 .NET 4.0(在我的 Windows 10 环境中可用)。
然后我尝试为较旧的运行时版本(2.0、3.0、3.5)构建 DLL,并且对于它们中的每一个都工作得很好。
当然,我一直在研究可能是什么问题,这是我到目前为止发现的有望解决问题(但没有解决)的内容:
- Cannot get to work VB.NET DLL referenced by VB6 client in reg-free scenario
- How to: Configure .NET Framework-Based COM Components for Registration-Free Activation(具体使用 DLL 清单
clrClass
元素中的runtimeVersion="v1.4"
属性)
目前我不知道还能做什么。我在 Internet 上找到的任何其他资源仅指向我在上面列出的建议之一。
我还能忽略什么?
更新:
一位同事提到这可能是一个 Delphi 奇怪的问题,并且是从非托管代码调用的。
我们正在使用 Embarcadero Seattle Delphi 10.
我在此处找到的信息的帮助下解决了问题:
Runtime Versions and Errors 0x80131700 and 0x8013101b
我已经尝试在 DLL 的程序集清单中添加 .NET CLR 版本。这可以根据 clrClass
部分中的 class 来完成。
我不知道的是,runtimeVersion
属性必须是完全限定的。
完整的 clrClass
部分现在如下所示:
<clrClass
clsid="{A0BDB20B-A6E4-4A36-A64C-CC9186DD1C3E}"
progid="TestSideBySide2"
threadingModel="Both"
name="TestSideBySide2.SideBySideClass"
runtimeVersion="v4.0.30319">
</clrClass>
根据上面链接的文档,其他 CLR 版本的版本条目应该是:
- v1.0.3705
- v1.1.4322
- v2.0.50727
- v4.0.30319