生成小型Windows二进制文件

时间:2009-09-29 21:57:52

标签: windows winsxs

在开发和部署本机Windows应用程序时,我经常需要安装运行时才能运行我的二进制文件,或者将库与我的二进制文件静态链接。例如,在使用Visual Studio 2008构建“Win32控制台”项目后,尝试在新的Windows 7映像上运行该程序会导致:

  

应用程序无法启动,因为它的并排配置不正确。请参阅应用程序事件日志或使用命令行sxstrace.exe工具获取更多详细信息。

这样的问题已在StackOverflow上的other posts中提出。

如何开发需要不在目标操作系统上的运行时的应用程序(即不需要安装可再发行软件包或私有/共享并排组件) ?如何避免使用msvc [mpr] 90.dll并只使用\ windows \ system32 *中的Windows API。{dll,sys}?

我正在思考来自demoscene的代码,但这种情况经常无法实现。

5 个答案:

答案 0 :(得分:4)

其他人已经就静态链接CRT做出了回应。如果你同时想要一个小二进制文件,那么你最好的选择是完全放弃CRT,并尽可能只使用Win32 API函数。您仍将获得一些CRT代码,最明显与启动相关(即调用main)和关闭(atexit处理等),但链接器不会链接您执行的CRT功能不使用。

您可以使用/Zl编译器开关完全避免连接CRT。这意味着main将不再有效,但是 - 您需要定义WinMain(名称无关紧要,但签名必须匹配,且必须为__stdcall),并且您必须通过链接器WinMain开关指定您的/entry: - 类函数的名称作为入口点。这将为您节省~30Kb的CRT代码(在.cpp上测试,空main)。

如果你采用后一种方式,你可能还需要处理编译器内在函数的问题。有些函数名义上由CRT定义(并在其标题中声明),但是由编译器专门处理,因此它在可能的情况下在调用时插入优化的汇编指令 - 示例为{{1} },memset,以及strlen中的一大块函数;可以找到完整列表here。既然你没有CRT,如果你需要这些功能,或者可以避免它,但是因为性能提高而更喜欢内在功能(例如,比<math.h>更难做),那么你必须自己声明它们,并使用memset。 E.g:

#pragma intrinsic

以上内容可以编译:

// Contains macros and typedef only, so safe to include without CRT.
// We need it here for size_t.
#include <stddef.h> 

extern "C"
{
    int abs(int);
    void* memset(void*, int, size_t); 
}

#pragma intrinsic(abs, memset)

int __stdcall main(void*, void*, char*, int)
{
    char tmp[10];
    memset(tmp, abs(-123), 10);
    return 0;
}

答案 1 :(得分:3)

通过/MT开关静态链接CRT(如果您正在使用它,也可以使用MFC)。

静态链接限制了你可以对DLL做些什么,但对于简单的可执行文件,它就像一个魅力。 (如果您正在运送DLL,则无论如何都可以随身携带私人程序集。)

答案 2 :(得分:2)

使用静态CRT。这不会对msvc * .dll产生依赖性。 CRT直接链接到您的程序。这不会创建依赖项,但会增加可执行文件的大小。

有关不同CRT选项的更多信息here

答案 3 :(得分:0)

静态链接运行时。 MS Visual C ++有选项/ MT(默认为/ MD)

答案 4 :(得分:0)

我认为一种方法是不使用Visual Studio而是依赖命令行SDK工具。 (你也可以选择如何配置VS来做你想做的事情,但这看起来更难。)例如:

cl /c app.cpp
link app.obj ws2_32.lib