【问题标题】:LoadLibrary() an EXE?LoadLibrary() 一个 EXE?
【发布时间】:2013-10-07 07:00:18
【问题描述】:

我有一个可执行文件(我使用 Visual C++ 10 创建的),我需要从我编写的另一个程序(相同的环境)中使用它的功能。由于复杂的部署要求,我不会详细介绍,因此我无法从所需的功能构建 DLL 并将其加载到两个程序中。

所以我想我可以__declspec(dllexport)EXE中的一些功能,然后LoadLibrary()会让我GetProcAddress()他们。

显然这是不可能的,尽管当我开始研究它时 - 它看起来是可行的。

具体来说,当您在 EXE 项目中使用 __declspec(dllexport) 函数时,Visual C++ 还会生成一个 lib 文件用于动态链接 - 所以您甚至不需要使用 LoadLibrary() - 只需链接到生成的库并调用功能。

不幸的是,主要问题是当您将生成的文件声明为 EXE 时,Visual C++ 会将“CRTmain”入口点添加到生成的文件中,而不是 DLL 获取的“CRTDLLmain”。当 Windows(自动)LoadLibrary() 主程序中的 EXE 时,它不会调用“CRTDLLmain”入口点(因为它不存在),模块的 C 运行时不会被初始化,并且作为结果所有有趣的工作(例如内存分配)都失败并出现了有趣的(*)运行时异常。

如下,我的问题是:有没有办法让 Visual C++ 将“CRTmain”入口点“CRTDLLmain”入口点都构建到结果文件中?

(*) “有趣”就像中国古语中的诅咒一样。

【问题讨论】:

  • 你能在 exe 中公开一个“init”函数来显式初始化 C 运行时吗?
  • @Asaf:我不知道怎么做 - 这是编译器自动执行的操作,据我所知没有公共接口。
  • 如果你在 exe 中调试你的'main'函数,我想你会看到为初始化 CRT 调用的确切函数(main() 在某个函数中调用,代码是裸露)。但另一个想法 - 如果 DLL 不可行,为什么不将功能提取到静态库并将其链接到两个 exe 中?
  • 1) 是的,但是 CRT 初始化序列是深层 VC++ 私有内部的 - 我宁愿不复制它,尤其是在不了解的情况下,尤其是在未来升级到更新的编译器时。我想我不能使用 API,除非它是公开的。

标签: c windows visual-studio-2010 visual-c++


【解决方案1】:

不! 问题是您要加载的 CRT 和 EXE 中使用了一些全局变量。您的主要 EXE 也是如此。那么内存分配应该如何工作呢?

如果您想使用这样的结构,您必须使用 DLL 来了解多线程、CRT 初始化以及所有其他内容。你需要这个!

但是 COM 自动化呢?在另一个 EXE 中使用您的代码不是一个简单的解决方案吗?

【讨论】:

  • 我看不出您的评论与讨论有何关联。一般来说,DLL(标准的,而不是伪装成这样的 EXE)可以有全局变量——因为 Windows 中的每个模块都有不同的堆。另外,我看不出多线程对这个问题有什么影响。
  • 关于 COM 自动化 - 你的意思是让我的可重用代码作为 COM 服务器?有趣的方法,但据我了解 COM 自动化,这将排除使用 EXE 作为可以运行的工具,它自己的 main 可以做一些有用的事情。
  • @Guss,我知道几年过去了,但是您可以将单个 EXE 用于 COM 服务器和普通客户端。 Microsoft Word 就是一个很好的例子。正常运行它,你会得到一个 UI。创建一个Word.Application 的实例,你会发现一个以winword.exe -Embedding 开头的进程。 The -Embedding flag is passed by COM.
  • 我知道构建 COM 服务器的选项,但由于部署要求、API 要求和安全性,我不想将功能公开为 COM 模块。但无论如何,如果这与我相关,我将不再担任职务。
【解决方案2】:

简短的回答是“不”。放眼望去,没有办法让 VC++ 做我想做的事,而且很可能没有任何其他编译器。

主要问题是大多数人都知道和喜爱的 main() 入口点并不是 C++ 可执行文件中的真正入口点:编译器需要做很多初始化工作才能将“C++ 运行时库”放到一个可用状态,以及初始化全局变量、静态变量等。这种初始化在共享库中使用的代码与在可执行文件中使用的代码不同,并且没有办法让一个人表现得像另一个人。

可以做的一件事是将共享功能构建到 DLL 中,并让主可执行文件将 DLL 作为资源嵌入,并从可执行文件的内存映射区域加载它(有几个代码示例如何在 stackoverflow 和网络上的其他地方使用 VC++ 执行此操作)。现在另一个程序可以通过从捆绑可执行文件中加载 DLL 来做同样的事情。

【讨论】:

    【解决方案3】:

    是的,这是可能的。

    http://www.codeproject.com/Articles/1045674/Load-EXE-as-DLL-Mission-Possible

    这个想法是 a) 修补 IAT,b) 在调用导出之前调用 CRT。

    【讨论】:

    • 哇,这真是太神奇了。我不再从事该项目,但尝试一下会很有趣,尽管我不了解 IAT 修补代码中发生的一半情况。
    猜你喜欢
    • 2011-09-11
    • 1970-01-01
    • 2016-12-08
    • 1970-01-01
    • 2015-09-30
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多