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

我正在使用Visual Studio 2005。

我想编译一个简单的程序,可以与任何独立于c ++运行时库版本安装的Windows 32位版本一起工作。

这个程序将调用GetModuleHandleGetProcAddress函数,而不需要任何其他函数调用,然后退出,当退出代码是函数地址时。

如何编译一个只依赖kernel32.dll和user32.dll的C ++程序,没有任何c ++运行库?

在您的项目选项下设置/NODEFAULTLIB 。 在较新版本的Visual C ++中,您还必须关闭堆栈溢出检查,因为这会导致编译器自动将调用插入到库函数中。

编辑:如果你的意思是“在任何32位Windows版本上运行”,你也将不得不使用editbin来更改PE头中的子系统版本字段。 否则,当你使用VC ++ 2005链接器进行构建时,你将被限制在(IIRC)Windows 2000以及更高版本,并且更新版本的VC ++更糟(默认情况下需要XP)。 Windows 2000是5.0,你想要指定3.5或其附近允许所有版本的NT除了Win9x。

您将需要定义自己的入口点,而不是使用mainWinMain 。 你的入口点是一个没有参数的void函数。 您必须使用/entry:funcName (其中funcName将被您想要用作入口点的函数的名称替换)替换为链接器的名称。

当你这样做时,你还必须指定子系统到链接器,如/subsystem:console 。 它通常根据它找到的函数的名称(即main – > console, WinMain – > Windows)推导子系统,但是当你使用自己的入口点时,必须明确指定它。 虽然你可能不想经常这样做,但是你可以明确地指定子系统,即使你没有指定自己的入口点,所以(例如)你可以使用main作为windows子系统程序的入口点,或者WinMain作为控制台程序的入口点。

我不确定为什么每个人都建议不要使用标准库 。 这种方法假定你想要你的代码在Windows 2000或更高版本上运行,不介意失去对Win 9x的支持。 您仍然可以使用C / C ++标准库 – 您可以在项目的C / C ++代码生成页面中使用/MT选项,这些页面将静态链接到标准库中。

不过,有两个注意事项,第一个是我自己:有一个动态链接的标准库的想法是,它的任何错误将被Windows Update(理论上)修补。 如果您静态链接库,则需要重新分发应用程序以修复标准库错误。 所以不建议。

其次,从MSDN关于编译器选项的文章:

小心不要混合运行时库的静态和动态版本。 在进程中运行时库的多个副本可能会导致问题,因为一个副本中的静态数据不会与另一个副本共享。 链接程序可以防止您在一个.exe文件中同时链接静态和动态版本,但是仍然可以以两个(或更多)运行时库副本结束。 例如,与运行库的静态(非DLL)版本链接的动态链接库可能会导致问题时使用与运行时库的动态(DLL)版本链接的.exe文件。 (您也应该避免在一个进程中混合库的调试版和非调试版)。

简而言之,如果您尝试构建与动态链接的标准库链接的其他组件,那么这会造成混淆。

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

编辑:结果,在depend.exe下,看起来像这样:(当然,我使用的是64位的Windows,它只适用于XP和更高版本…如果你想知道这是什么样子在32-想想如果64位不在那里!)。

depends.exe程序只显示一个动态依赖项kernel32.dll

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

你实际上并不需要User32.dll,唯一真正无法删除的是coreel32.dll和Ntdll.dll – 这些被PsCreateProcess注入到进程空间(即内核如何创建新进程的一半) 。