【问题标题】:Accessing a COM object访问 COM 对象
【发布时间】:2013-03-07 23:54:34
【问题描述】:

我有一个使用 cpp COM 对象的 c# 解决方案。 COM 对象和 c# 应用程序都是专门为 64 位系统构建的。当我从 VS 2010 运行时,该解决方案可以正常工作。但是,在我将它安装到不同的系统(64 位)后,却找不到 COM 对象。

我认为这是因为它在安装过程中没有注册,但我似乎在这样做时遇到了麻烦。当我尝试时

regsvr32 ComObject.dll

我收到一条错误消息,指出“模块 'ComObject.dll' 无法加载。确保二进制文件存储在指定路径或对其进行调试以检查二进制文件或相关 .DLL 文件是否存在问题。

我正在从 dll 所在的目录调用 regsvr32,并且我三次检查名称是否输入正确。我尝试在安装程序中注册它,将 dll 注册开关设置为 vsdrfCOM,并收到警告“无法为名为‘ComObject.dll’的文件创建注册信息。这很可能是因为 dll 是在单独的解决方案中构建并添加的将此解决方案作为资源。

因此,我可以将它安装在我的开发系统上,并且运行良好。我认为这是因为 VS 已经注册了 dll。 (目前,该 dll 不是安装程序的一部分,因为它会导致问题,所以我将其复制到调试文件夹中。

有没有人知道我可能做错了什么?

附加信息:

根据 David Heffernan 的指示,我以正确的方式运行 Dependency Walker。以下是我收到错误消息“找不到入口点 DllRegisterServer”之前的最后几行。

...
GetProcAddress(0x000007FEFCBB0000 [UXTHEME.DLL], "DrawThemeText") called from "COMCTL32.DLL" at address 0x000007FEFCC2FD99 and returned 0x000007FEFCBB61F8.
GetProcAddress(0x000007FEFCBB0000 [UXTHEME.DLL], "EndBufferedAnimation") called from "COMCTL32.DLL" at address 0x000007FEFCC2FD99 and returned 0x000007FEFCBB4F98.
GetProcAddress(0x000007FEFCBB0000 [UXTHEME.DLL], "GetBufferedPaintDC") called from "DUSER.DLL" at address 0x000007FEFC58069D and returned 0x000007FEFCBC0BC0.
GetProcAddress(0x000007FEFCBB0000 [UXTHEME.DLL], "GetBufferedPaintTargetDC") called from "DUSER.DLL" at address 0x000007FEFC58069D and returned 0x000007FEFCBC0B5C.
GetProcAddress(0x000007FEFCBB0000 [UXTHEME.DLL], "EndBufferedPaint") called from "DUSER.DLL" at address 0x000007FEFC58069D and returned 0x000007FEFCBB4F98.
GetProcAddress(0x000007FEFC570000 [DUSER.DLL], "FindGadgetFromPoint") called from "COMCTL32.DLL" at address 0x000007FEFCC2FD99 and returned 0x000007FEFC581F40.
GetProcAddress(0x000007FEFC570000 [DUSER.DLL], "ForwardGadgetMessage") called from "COMCTL32.DLL" at address 0x000007FEFCC2FD99 and returned 0x000007FEFC582CAC.

按确定后,我得到:

LoadLibraryW("comctl32.dll") called from "USER32.DLL" at address 0x00000000779A91DC.
LoadLibraryW("comctl32.dll") returned 0x000007FEFCC10000.
GetProcAddress(0x000007FEFCC10000 [COMCTL32.DLL], "RegisterClassNameW") called from "USER32.DLL" at address 0x00000000779A91F9 and returned 0x000007FEFCC38024.
GetProcAddress(0x000007FEFCBB0000 [UXTHEME.DLL], "BufferedPaintStopAllAnimations") called from "COMCTL32.DLL" at address 0x000007FEFCC2FD99 and returned 0x000007FEFCBCE408.
GetProcAddress(0x000007FEFCBB0000 [UXTHEME.DLL], "BufferedPaintUnInit") called from "COMCTL32.DLL" at address 0x000007FEFCC2FD99 and returned 0x000007FEFCBBFA04.
GetProcAddress(0x000007FEFC570000 [DUSER.DLL], "DisableContainerHwnd") called from "COMCTL32.DLL" at address 0x000007FEFCC2FD99 and returned 0x000007FEFC57A38C.
GetProcAddress(0x000007FEFCBB0000 [UXTHEME.DLL], "BufferedPaintUnInit") called from "DUSER.DLL" at address 0x000007FEFC58069D and returned 0x000007FEFCBBFA04.
GetProcAddress(0x000007FEFC570000 [DUSER.DLL], "DUserFlushMessages") called from "COMCTL32.DLL" at address 0x000007FEFCC2FD99 and returned 0x000007FEFC57A8A0.
GetProcAddress(0x000007FEFC570000 [DUSER.DLL], "DUserFlushDeferredMessages") called from "COMCTL32.DLL" at address 0x000007FEFCC2FD99 and returned 0x000007FEFC57A830.
GetProcAddress(0x000007FEFC570000 [DUSER.DLL], "DeleteHandle") called from "COMCTL32.DLL" at address 0x000007FEFCC2FD99 and returned 0x000007FEFC574BB8.
GetProcAddress(0x00000000779A0000 [USER32.DLL], "UnregisterMessagePumpHook") called from "DUSER.DLL" at address 0x000007FEFC57B8A9 and returned 0x00000000779A8564.
DllMain(0x0000000180000000, DLL_PROCESS_DETACH, 0x0000000000000000) in "MAPIEX64.DLL" called.
DllMain(0x0000000180000000, DLL_PROCESS_DETACH, 0x0000000000000000) in "MAPIEX64.DLL" returned 1 (0x1).
DllMain(0x000007FEFB5F0000, DLL_PROCESS_DETACH, 0x0000000000000000) in "MAPI32.DLL" called.
DllMain(0x000007FEFB5F0000, DLL_PROCESS_DETACH, 0x0000000000000000) in "MAPI32.DLL" returned 1 (0x1).
DllMain(0x0000000051AF0000, DLL_PROCESS_DETACH, 0x0000000000000000) in "MFC100.DLL" called.
DllMain(0x0000000051AF0000, DLL_PROCESS_DETACH, 0x0000000000000000) in "MFC100.DLL" returned 1 (0x1).
DllMain(0x000007FEF9E60000, DLL_PROCESS_DETACH, 0x0000000000000000) in "MSIMG32.DLL" called.
...
Exited "REGSVR32.EXE" (process 0x23A0) with code 4 (0x4).

除了提到 DllRegisterServer 之外,没有具体的错误消息。我确实以管理员身份运行。运行时,模块列表中出现另一个错误:打开文件时出错。该系统找不到指定的路径。这是有道理的,因为它是一个空字符串。这旁边有一个问号,所以我假设它是延迟加载。

我在 regsvr32.exe 上再次运行 Dependency Walker,得到以下错误:

LoadLibraryExW("C:\Program Files\Project\ComObject.dll", 0x0000000000000000, LOAD_WITH_ALTERED_SEARCH_PATH) returned NULL. Error: The specified module could not be found (126).

我还在日志文件的顶部发现了这些错误:

Error: Modules with different CPU types were found.
Warning: At least one delay-load dependency module was not found.
Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.

感谢大家的帮助。

【问题讨论】:

  • COM 对象可能缺少某些依赖项?我知道 COM 服务器不会注册,因为缺少依赖项。
  • @RobGoodwin - 我在上面使用了 Dependency Walker,但它缺少 IESHIMS.dll,但我的理解是,如果存在适当的错误处理,这是一个不需要的可选 dll。我没有开发 cpp 代码,但可以访问它。如果我确实需要确保它包含在 dll 中,我将如何添加它,为什么没有它 dll 会运行?我的 cpp 技能非常基础。
  • 尝试上述相同 DLL 的发布版本。奇怪的是,您的调试版本依赖于 MSVCRTD.DLL、MSVCPD.DLL 等,这些都不是在干净的机器上。正确的 VC 运行时 redist 包加上 DLL 的发布版本可能会消除 主要 依赖问题。
  • @WhozCraig - 感谢您的回复。 Com 对象是一个发布版本。从 VS 访问时它正在工作,所以我知道可以注册(或任何 VS 对其进行的操作,以便它工作)。根据 Dependency Walker 的说法,dll 中缺少 IESHIMS.DLL,但我不知道如何添加它。
  • 首先确保使用了正确的 regsvr32.exe。 IESHIMS.DLL 依赖项(以及其他一些依赖项)通常是红鲱鱼,因为它们是延迟加载目标(不要问)。您的 DLL 使用 是否有 C 运行时和/或 WIN32 API 本身未严格提供的任何内容?我会从这些开始。

标签: c# c++ visual-studio-2010 com


【解决方案1】:

这可能是一个依赖问题。使用 Dependency Walker 解决它。使用 Profile 菜单启动一个进程。运行 regsvr32。指定命令行参数和工作目录。

我的猜测是问题是缺少 MSVC 运行时,但该工具会揭示导致失败的原因。

您需要运行 Dependency Walker 提升的权限才能进行注册。

【讨论】:

  • 感谢您的回复。我确实发现找不到 IESHIMS.DLL,但不太确定如何将其添加到 dll 中。我对 cpp 项目的经验很少。我的主要困惑是VS为什么可以注册dll,但我不能手动?
  • IESHIMS 不相关。这是一个可选的延迟加载 dll。但我不认为你理解我的回答。您尚未在配置文件模式下运行。
  • 在做这个之前,我之前没有使用过 Dependency Walker,所以我仍然在快速了解需要做什么以及如何解释结果。当我点击 Profile 时,我可以选择开始和停止分析,但它们都是灰色的。
  • 您必须先加载可执行文件。在这种情况下,它是 regsvr32。
  • 我这样做了,在顶部发现一个错误,说找到了具有不同 CPU 类型的模块。我确实将它编译为 x64,但我无法检查所有依赖库是否都是 x64。这可能是问题吗?
【解决方案2】:

Windows 经常对是否应该从 System32SysWOW64 目录运行应用程序感到困惑。

尝试显式运行 regsvr32 的 64 位版本:

%SystemRoot%\System32\regsvr32.exe ComObject.dll

【讨论】:

  • 这不会运行 64 位 regsvr32。这运行与命令提示符具有相同位数的那个。因为文件重定向器。所以这将从 32 位 cmd.exe 运行 32 位。此答案中的代码与 Q 中的代码相同。如果是位数,则错误会有所不同。
【解决方案3】:

感谢 David Hefferman 和 WhozCraig;您的信息帮助我开始使用 Dependency Walker,在我弄清楚如何解释它发现的内容后,我可以看到它将被证明是一个强大的工具。它还帮助我找出可能的问题。

最后,我走向了不同的方向。我将 cpp 项目添加到我的主项目中,然后在我的安装程序中使用了输出。这导致它正确注册。我仍然不确定这与运行 regsvr32 有何不同,但无论有什么不同,它都会导致事情开始工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    • 2016-08-12
    • 2012-10-10
    • 2013-01-14
    • 2017-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多