由于 0x8007065E "Data of this type not supported",DllSurrogate 未加载
DllSurrogate not loading because of 0x8007065E "Data of this type not supported"
我正在尝试使旧的 Delphi 32 位 DLL 可用于我的 C# 应用程序。使用默认系统 DLL 代理 (dllhost.exe) 似乎是最舒适的解决方案。
为了证明这可行,我创建了一个最小的 32 位测试 DLL Delphi,它只用一种方法实现了一个接口
HRESULT Add(double a, double b, double* c);
在我的 C# 测试程序中,我首先使用了有效的进程内激活。但是因为要突破32/64位的障碍我们不得不使用DLL Surrogate。所以我添加了必要的注册表项(AppID 等)来完成这项工作,但目前仍将两个模块(DLL 和 C# 测试项目)保留为 32 位。
为确保 DLL 未在进程中加载,我 'pinvoked' CoCreateInstance 并像这样使用它:
var adapter = CoCreateInstance(
new Guid("96810C5C-BA59-49D4-9732-EF902B8EFA72"),
null,
CLSCTX.CLSCTX_LOCAL_SERVER,
new Guid("00000000-0000-0000-C000-000000000046"));
后一个 GUID 是 IUnknown,所以我什至没有使用我的自定义界面进行此测试(当然我是从我的自定义界面开始的)。
问题是这段代码已经失败了:
0x8007065E "Data of this type not supported"
而且我不知道它在谈论什么数据。我认为可能只支持 VARIANT 类型,所以我将签名更改为以下内容,为了测试,甚至省略了 'out' 参数:
HRESULT Add(VARIANT a, VARIANT b);
还是一样的错误!
知道这里出了什么问题吗?
更新 1
CoCreateInstance的声明是这样的
[Flags]
enum CLSCTX : uint
{
CLSCTX_INPROC_SERVER = 0x1,
CLSCTX_INPROC_HANDLER = 0x2,
CLSCTX_LOCAL_SERVER = 0x4,
CLSCTX_INPROC_SERVER16 = 0x8,
CLSCTX_REMOTE_SERVER = 0x10
}
[DllImport("ole32.dll", ExactSpelling = true, PreserveSig = false)]
[return: MarshalAs(UnmanagedType.Interface)]
static extern object CoCreateInstance(
[In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
[MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter,
CLSCTX dwClsContext,
[In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
更新 2
为了完整起见,我应该提到在 Delphi 中,界面是通过 Delphi 类型库编辑器设计的。在 C# 中,我然后将 COM 对象作为引用导入,据我所知,它从类型库创建了一个包装器。
更新 3
我刚刚用 C# 实现了相同的 COM 测试对象,并使其在 COM 中可见。我什至没有导入类型库来创建运行时可调用包装器,而只是尝试使用 CoCreateInstance 获取 IUnknown。同样的错误信息!
(顺便说一句,我的测试机器运行 Windows 10)
更新 4
我在 Delphi 中重写了客户端并通过 DLL 代理实例化了两个 COM 对象实现(Delphi 和 C#)。来自 CoCreateInstance 的相同错误消息!
事实证明,所有这些巨大的混乱都是由不正确的注册表设置引起的。要添加到我的 COM 对象的 AppID 条目的 DllSurrogate 值必须留空才能使用系统默认值 dllhost.exe。但是它仍然必须是 REG_SZ 类型,而我的类型被意外创建为 REG_BINARY.
我正在尝试使旧的 Delphi 32 位 DLL 可用于我的 C# 应用程序。使用默认系统 DLL 代理 (dllhost.exe) 似乎是最舒适的解决方案。
为了证明这可行,我创建了一个最小的 32 位测试 DLL Delphi,它只用一种方法实现了一个接口
HRESULT Add(double a, double b, double* c);
在我的 C# 测试程序中,我首先使用了有效的进程内激活。但是因为要突破32/64位的障碍我们不得不使用DLL Surrogate。所以我添加了必要的注册表项(AppID 等)来完成这项工作,但目前仍将两个模块(DLL 和 C# 测试项目)保留为 32 位。
为确保 DLL 未在进程中加载,我 'pinvoked' CoCreateInstance 并像这样使用它:
var adapter = CoCreateInstance(
new Guid("96810C5C-BA59-49D4-9732-EF902B8EFA72"),
null,
CLSCTX.CLSCTX_LOCAL_SERVER,
new Guid("00000000-0000-0000-C000-000000000046"));
后一个 GUID 是 IUnknown,所以我什至没有使用我的自定义界面进行此测试(当然我是从我的自定义界面开始的)。
问题是这段代码已经失败了:
0x8007065E "Data of this type not supported"
而且我不知道它在谈论什么数据。我认为可能只支持 VARIANT 类型,所以我将签名更改为以下内容,为了测试,甚至省略了 'out' 参数:
HRESULT Add(VARIANT a, VARIANT b);
还是一样的错误!
知道这里出了什么问题吗?
更新 1
CoCreateInstance的声明是这样的
[Flags]
enum CLSCTX : uint
{
CLSCTX_INPROC_SERVER = 0x1,
CLSCTX_INPROC_HANDLER = 0x2,
CLSCTX_LOCAL_SERVER = 0x4,
CLSCTX_INPROC_SERVER16 = 0x8,
CLSCTX_REMOTE_SERVER = 0x10
}
[DllImport("ole32.dll", ExactSpelling = true, PreserveSig = false)]
[return: MarshalAs(UnmanagedType.Interface)]
static extern object CoCreateInstance(
[In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
[MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter,
CLSCTX dwClsContext,
[In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
更新 2
为了完整起见,我应该提到在 Delphi 中,界面是通过 Delphi 类型库编辑器设计的。在 C# 中,我然后将 COM 对象作为引用导入,据我所知,它从类型库创建了一个包装器。
更新 3
我刚刚用 C# 实现了相同的 COM 测试对象,并使其在 COM 中可见。我什至没有导入类型库来创建运行时可调用包装器,而只是尝试使用 CoCreateInstance 获取 IUnknown。同样的错误信息! (顺便说一句,我的测试机器运行 Windows 10)
更新 4
我在 Delphi 中重写了客户端并通过 DLL 代理实例化了两个 COM 对象实现(Delphi 和 C#)。来自 CoCreateInstance 的相同错误消息!
事实证明,所有这些巨大的混乱都是由不正确的注册表设置引起的。要添加到我的 COM 对象的 AppID 条目的 DllSurrogate 值必须留空才能使用系统默认值 dllhost.exe。但是它仍然必须是 REG_SZ 类型,而我的类型被意外创建为 REG_BINARY.