C++ 编译一个C++;仅依赖于kernel32.dll和user32.dll的程序?

C++ 编译一个C++;仅依赖于kernel32.dll和user32.dll的程序?,c++,windows,visual-c++,runtime,C++,Windows,Visual C++,Runtime,我在VisualStudio2005工作 < >我想编译一个简单的程序,它将与任何安装在C++运行库库中的Windows 32位版本无关。 当退出代码是函数地址时,该程序将调用GetModuleHandle和GetProcAddress函数,而不进行任何其他函数调用,然后退出 如何编译一个只依赖于Kaln32.DLL和UsSeri3dLL的C++程序,没有任何C++运行库, SET>代码> /NoDebug(代码)>在项目选项下。在Visual C++的更新版本中,还必须关闭堆栈溢出检查,因为这

我在VisualStudio2005工作

< >我想编译一个简单的程序,它将与任何安装在C++运行库库中的Windows 32位版本无关。 当退出代码是函数地址时,该程序将调用
GetModuleHandle
GetProcAddress
函数,而不进行任何其他函数调用,然后退出


<>如何编译一个只依赖于Kaln32.DLL和UsSeri3dLL的C++程序,没有任何C++运行库,

SET>代码> /NoDebug(代码)>在项目选项下。在Visual C++的更新版本中,还必须关闭堆栈溢出检查,因为这些导致编译器自动插入对库函数的调用。


编辑:如果您的意思是“在任何32位Windows版本上运行”,则还必须使用
editbin
更改PE标题中的subsystem version字段。否则,在使用VC++2005链接器构建时,您只能使用(IIRC)Windows 2000及更高版本,而VC++的更新版本更糟糕(默认情况下需要XP)。Windows 2000是5.0,您可能希望指定3.5或更高版本以允许除Win9x之外的所有NT版本。

您需要定义自己的入口点,而不是使用
main
WinMain
。您的入口点是一个不带参数的void函数。您必须使用
/entry:funcName
将其名称指定给链接器(其中
funcName
将替换为您为要用作入口点的函数指定的任何名称)


执行此操作时,还必须指定链接器的子系统,如
/subsystem:console
中所示。它通常根据找到的函数名推断子系统(即,
main
->控制台,
WinMain
->窗口),但当您使用自己的入口点时,必须明确指定它。虽然您可能不想经常这样做,但即使您没有指定自己的入口点,也可以显式指定子系统,因此(例如)您可以使用
main
作为windows子系统程序的入口点,或者
WinMain
作为控制台程序的入口点。

检查微小的c库。也可以静态链接。

我不知道为什么每个人都反对使用标准库。此方法假定您希望代码在Windows 2000或更高版本上运行,并且不介意失去对Win 9x的支持。您仍然可以使用C/C++标准库-您可以在项目的C/C++代码生成页面中使用
/MT
选项,该选项将静态链接到标准库中

然而,有两个注意事项,第一个来自我:拥有一个动态链接的标准库的想法是,其中的任何错误都会通过Windows Update(理论上)得到修补。如果静态链接库,则需要重新分发应用程序以修复标准库错误。所以不建议这样做。

其次,从MSDN文章中可以看出:

注意不要将静电和静电混用 运行时的动态版本 图书馆。有多份的 进程中运行时库的 可能会导致问题,因为静态 一个副本中的数据不与共享 另一份。链接器阻止 您可以避免使用静态和动态链接 一个.exe文件中的动态版本, 但你最终还是可以得到两个(或更多) 更多)运行时的副本 图书馆。例如,动态链接 与静态链接的库 运行时的(非DLL)版本 库在使用时可能会导致问题 使用链接到的.exe文件 的动态(DLL)版本 运行时库。(你也应该 避免混合调试和非调试 一个数据库中的库版本 过程。)

简言之,如果您试图构建其他与动态链接的标准库链接的组件,那么这样做可能会导致混淆

当然,另一个缺点是这也会使可执行文件变大

编辑:depends.exe下的结果如下:(当然,我使用的是64位Windows,它只适用于XP和更高版本……如果你想知道32位Windows上的结果,想象一下如果没有
64
s!)


实际上,您也不需要User32.dll,唯一真正无法删除的是Kernel32.dll和Ntdll.dll-它们由PsCreateProcess(即内核创建新进程的一半)注入到进程空间中

+1这是一个好的SO问题的缩影。如果我可以问的话,这个程序的目的是什么?我正在实现从64位进程到32位进程的代码注入,我需要帮助程序32位程序来找到一些函数的地址。也许你应该问这个问题,因为有比创建助手程序更好的方法。在我自己的开源项目(检查我的配置文件)中,我有64位到32位的DLL注入,为此我需要检索32位LoadLibrary的地址。您所要做的就是自己映射DLL并查找函数地址,然后添加由远程进程加载的DLL的基址。虽然您确实希望指定
/nodefaultlib
,但它本身只会给您
未解决的外部
错误。真正的关键是使用您自己的入口点来消除对库的依赖。@Jerry:我想您可以根据链接器在默认情况下查找的任何内容来命名您的入口点(
wCRTWinMain
或类似内容),但我同意使用
/entry
更干净。我从未尝试过,所以我想它可能会起作用,但是不能确定(如果没有测试,很难说链接器可能使用/调用/依赖什么魔法)。不管您是否使用
/entry:
来指定它是什么,您都必须定义入口点