【问题标题】:Wrapping a 32-bit COM shell extension within a "thin" 64-bit DLL wrapper在“瘦”64 位 DLL 包装器中包装 32 位 COM shell 扩展
【发布时间】:2015-08-19 08:11:41
【问题描述】:

前提:

我有一个旧的 32 位 COM shell 扩展(用 C++ 编写)。在与较新的 64 位系统多年不兼容之后,我们现在对其进行更新以在 64 位 Windows 环境中工作。

诀窍:

32 位 COM DLL 包含对第三方库的依赖项,没有可用的 64 位版本。因此,我们不能简单地“以 64 位重新编译”。鉴于此限制,我们决定最简单的方法是创建一个“瘦”的 64 位 DLL;本质上是一个空 DLL,仅定义所需的接口,并将所有调用重定向到底层 32 位 COM DLL。

我相信 64 位 COM DLL 和 32 位 COM DLL 之间的这种通信是可能的,通过使用 COM 代理。不幸的是,这似乎是一个非常具体/小众的话题,我一直无法找到很多关于如何从 64 位 COM DLL 调用 32 位 COM API 的资源。

问题:

  • 对于启用 32 位 COM DLL 的 64 位功能,这种“瘦 COM 包装器”是否合理?
  • 这种方法是否有任何理由不适用于 Windows Shell 扩展?
  • 64 位接口定义是否会使用与其 32 位对应物相同的 GUID?
  • 这是过去记录的策略吗?
  • 是否有任何好的资源可以从 64 位 COM DLL 中调用 32 位 COM API?

说明:

这个问题有许多独特之处,使其与“Using 32-bit shell extensions in Windows 7 64-bit”问题不同。

我不是在问是否可以在 64 位资源管理器进程中加载​​ 32 位 shell 扩展,就像引用的问题那样。相反,我想问是否有可能创建一个瘦 64 位 DLL 实现,它充当 64 位资源管理器进程和 32 位实现之间的桥梁。

明确地说,这是不可能的

但也许这是

【问题讨论】:

  • 不,你不能。虽然 COM 代理 作为一个概念可以在 x64 客户端和托管在 32 COM 代理中的 32 位进程 COM 服务器之间使用,但 32 位和 64 位的混合并不重要,但对于 Windows Shell 不起作用,它要求所有扩展都与源自操作系统的 Windows 资源管理器进程的“位”相匹配。因此,如果操作系统是 64 位的,那么扩展也必须如此。 – stackoverflow.com/questions/13747836/…
  • 在这个特定的提议中,shell 扩展 DLL 的位级别为 64 位。 在 64 位 DLL 中,然而,具体实现将通过 COM 代理重定向到 32 位 DLL。
  • 原始的 32 位 shell 扩展必须托管在某个东西上,可以替代,但它需要模仿我怀疑的 32 位 Windows 资源管理器的所有相关 shell 扩展托管功能,这不是一项简单的任务。与 ActiveX 一样,组件和“站点”(在本例中为资源管理器)之间有很多双向通信。特别是如果扩展是 shell 命名空间扩展。根据扩展的类型,如果没有合适的生态系统来托管它,就不能仅仅加载 COM 扩展。
  • 考虑改写上面的图表。在图中,绿色框不能充当COM 代理项。根据定义,COM 代理是一个 Windows 进程,但您的绿框必须是一个进程内 COM 服务器(即 .DLL),以便加载到 64 位 Windows 资源管理器中.
  • @BTownTKD,只要您不必处理 COM 无法编组的数据,您就可以这样做。并且您的瘦 64 位 DLL 可能需要处理来自 32 位代理的请求。例如,您必须将在 32 位 DLL(使用 CoCreateInstance 或类似)中创建 Explorer 对象转换为对 64 位 DLL 的请求(如果您使用的是 IClassFactory::CreateInstance,这基本上只需要您获取工厂从 64 位 DLL 而不是 CoGetClassObject)。

标签: c++ windows com 32bit-64bit shell-extensions


【解决方案1】:

是的,使用 DCOM 是可行的,最糟糕的问题是为 DCOM“组件”设置权限并进行数据封送处理。

这种“瘦 COM 包装器”是否是一种合理的方法,用于启用 32 位 COM DLL 的 64 位功能?

是的,我们曾经这样做过,当时我们必须提供一个同时具有 32 位和 64 位实现的进程内 COM 服务器。我们基本上有这样的瘦服务器,它将以 32 位和 64 位实现(消费者将加载适当的)并将调用重定向到托管在 DCOM 中的 32 位 outproc 服务器。

是否有任何理由这种方法不适用于 Windows Shell 扩展?

您可能无法正确设置 outproc 服务器的权限。这很可能会奏效。无法想象任何其他原因。

64 位接口定义是否会使用与其 32 位对应物相同的 GUID?

是的。 COM 接口是一个契约。您可以根据需要拥有任意多个合约的实现。

有没有什么好的资源可以从 64 位 COM DLL 中调用 32 位 COM API?

没有什么特别的要求。只需用CLSCTX_ALL 调用CoCreateInstance() 即可。

您主要关心的是编组。您必须在客户端和服务器之间编组数据,这些数据现在将处于不同的进程中。您最好的选择是使用自动化封送处理(又名 typelib 封送处理)。如果碰巧原始接口与自动化不兼容,则尝试引入与自动化兼容的新接口,然后您的包装器将作为适配器服务。您可能无法为您的任务设计新的自动化兼容界面,但请尝试这样做,因为这是您最好的选择。

当任何事情发生故障时 - 某些事情没有编组,一些相关文件未找到 - 使用进程监视器来查看发生了什么失败。

【讨论】:

    【解决方案2】:

    我们有 64 位应用程序,它成功地使用了 32 位的 COM 应用程序(例如 VB6 的应用程序)。这看起来很复杂,但实际上您只需为您尝试使用的 COM 组件添加一些注册表项,然后您就可以使用它了。您可以在此处查看详细信息:

    http://www.gfi.com/blog/32bit-object-64bit-environment/ http://www.codeproject.com/Tips/267554/Using-bit-COM-Object-from-bit-Application

    所以是的,它会起作用,但当然这里有额外的复杂性,简单的解决方案通常是最好的。

    或者,您始终可以将 32 位功能包装为服务或类似的东西并以这种方式访问​​它。或者作为可执行文件并使用文本文件或其他东西进行通信。

    【讨论】:

    • 虽然适用于 COM,但它不适用于在具有 32 位 COM 扩展的 64 位 Windows 上运行的 64 位 Windows Shell。所有扩展都必须匹配操作系统的位。 stackoverflow.com/questions/13747836/…。 Windows Shell 扩展未作为“[windows] 服务” 实现
    • 对于外壳扩展,是的,您需要扩展与操作系统相同(尽管在 64 位上,如果 32 位应用程序使用旧式文件对话框,那么您还需要 32 个外壳扩展!) .确实如此,但如果为该组件设置了 dllsurrogate,这些扩展确实都可以使用 32 COM 组件。
    猜你喜欢
    • 1970-01-01
    • 2020-08-30
    • 1970-01-01
    • 2013-04-04
    • 2012-05-22
    • 2011-01-05
    • 1970-01-01
    • 2012-11-24
    • 1970-01-01
    相关资源
    最近更新 更多