将 32 位 dll 转换为 64 位

Posted

技术标签:

【中文标题】将 32 位 dll 转换为 64 位【英文标题】:Converting 32 bit dll to 64 bit 【发布时间】:2021-01-22 13:37:50 【问题描述】:

我不得不切换到 Office 64 位(2019,Professional Plus)。我有大量的 VBA 脚本,其中大多数都调用了一个用普通 C 语言编写并用非常旧的 Developer Studio 97 编译的旧 32 位 dll。我设法用 Visual Studio 2019 将它重新编译为 64 的 C++ dll位,我遇到了 2 个问题:函数 MessageBox(和 MessageBoxA)被标记为“未定义”。解决方法:我暂时将它们替换为 OutputDebugStringA 并且 DLL 编译正常。

从 VBA 调用函数,加载失败。感谢ProcessorMonitor,我发现我的dll 试图加载VCRUNTIME140D.dll 和UCRBASED.dll。我从互联网上下载了它们,我发现我必须将它们放在 C:\Program Files\Microsoft Office\root\Office16 中。但这还不够! VCRUNTIME140D.dll必须也放在C:\WINDOWS\SYSTEM32!

此时,我的 DLL 可以作为 64 位 dll 正常工作。

下一个惊喜是,重启后,由于缺少VCRUNTIME140_APP.dll,再次加载失败(请注意“140”后面没有“D”)!下载并放置在 C:\Program Files\Microsoft Office\root\Office16 中,DLL 可以正常工作。

我尝试将其编译为“静态”(“代码生成”->“运行时库”->“多线程”而不是“多线程 dll”),但出现错误: MSB8024 不支持使用静态版本的 C++ 运行时库。

在某处我读到 VCRUNTIME140 与 Visual Studio 2014 相关......很奇怪,但我是否也错过了该版本中的一些 .obj 以进行静态链接?为什么我需要旧系统中的元素?

回到 MessageBox 问题,我尝试了一个简单的 c++ 64 位控制台应用程序,并且接受了完全相同的函数并按预期工作,所以我猜想是头文件中的一些#ifdef 排除了 dll 中的声明。在我的头文件中移动了 MessageBox 声明,编译成功,但是(我猜到了)MessageBox 的链接器“未解析的外部”出现了。

此时,我的问题是: - 是否可以创建 64 位 static .dll? -是不是正常我必须从网上下载以上3个dll并将它们复制到一些目录中? - 可以在 64 位 dll 中使用普通的 MessageBox(句柄、文本、标题、按钮)吗?

谢谢。

【问题讨论】:

VCRUNTIME140D.dll 和 UCRBASED.dll 表示你依赖于调试运行时。无论您使用什么代码,都应该重新构建到发布配置。 我从网上下载的 这实际上违反了 Visual Studio 许可。您不应该下载这些文件。这些文件应该由您安装并用于调试的 Visual Studio 提供。您需要安装较新版本的 Visual Studio。 140 适用于 Visual Studio 14.0,即 2015。 静态 DLL 在术语上是矛盾的。 DLL 还应始终使用运行时的 DLL 版本,以便与应用程序共享 - 例如,拥有两个不同的堆只会带来麻烦。 @drescherjm 删除了 3 个 dll,在发布模式下编译我得到运行时错误 53。使用进程监视器,我看到“excel.exe”试图加载 VCRUNTIME140D.DLL。我想我有最新版本的 Visual Studio:我是在 10 月 5 日从微软官方网站下载的。 【参考方案1】:

最后,感谢 rustyx 的直觉,我发现我正在使用适合“应用程序”开发的“解决方案”。 (被调用的 dll 名称中的字符串 _APP 就表明了这一点!)我设法切换到“桌面”解决方案,现在加载的 dll 没有 _APP 后缀。 MessageBox 功能可以正常工作,无需在库中进行任何特定设置。

VCRUNTIME140D.DLL(调试版)和 VCRUNTIME140.DLL(发布版)存在于我安装的安装中,而它们是 Visual Studio 2019(以及 2015 和 2017)的一部分。 p>

最后,在这种情况下,现在可以生成静态 dll,VCRUNTIME140.DLL(以及更多)在运行时不会加载,但相同的代码是静态链接的。垃圾箱展示了它。 动态链接: USER32.dll VCRUNTIME140.dll api-ms-win-crt-filesystem-l1-1-0.dll api-ms-win-crt-stdio-l1-1-0.dll api-ms-win-crt-heap-l1-1-0.dll api-ms-win-crt-string-l1-1-0.dll api-ms-win-crt-runtime-l1-1-0.dll 内核32.dll 静态链接: USER32.dll KERNEL32.dll

所有问题都解决了!

【讨论】:

很高兴您得到了解决方案,感谢您的分享,如果您将它们标记为答案,我将不胜感激,这将对其他社区有益。

以上是关于将 32 位 dll 转换为 64 位的主要内容,如果未能解决你的问题,请参考以下文章

在 MS VC 2013 Express 中将 C++ dll 从 32 位转换为 64 位

将 access mde 从 32 位转换为 64 位

如何将 64 位 void 指针转换为 32 位 void 指针?

将 32 位 android 应用程序转换为 64 位应用程序

找不到指定的模块 - 64 位 dll

将 32 位动态库转换为 64 位的 osx