生成小型Windows二进制文件

生成小型Windows二进制文件,windows,winsxs,Windows,Winsxs,在开发和部署本机Windows应用程序时,我通常需要先安装运行时,然后才能运行二进制文件,或者将库与二进制文件静态链接。例如,在使用Visual Studio 2008构建“Win32 Console”项目后,尝试在新的Windows 7映像上运行该程序会导致: 应用程序无法启动,因为其并行配置不正确。有关详细信息,请参阅应用程序事件日志或使用命令行sxstrace.exe工具 像这样的问题已经在StackOverflow上提出来了 如何开发不需要目标操作系统上没有的运行时的应用程序(即不需要安

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

应用程序无法启动,因为其并行配置不正确。有关详细信息,请参阅应用程序事件日志或使用命令行sxstrace.exe工具

像这样的问题已经在StackOverflow上提出来了

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


我在考虑demoscene中的代码,但这通常不可用。

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


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

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


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

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


静态链接在某种程度上限制了您对DLL的使用,但对于简单的可执行文件,它就像一个魅力。(如果您正在运送DLL,您始终可以运送专用程序集。)

通过
/MT
开关静态链接CRT(同样,如果您正在使用MFC)


静态链接在某种程度上限制了您对DLL的使用,但对于简单的可执行文件,它就像一个魅力。(如果您正在运送DLL,您始终可以运送专用程序集。)

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

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

< P>其他已对CRT静态链接进行了响应。如果同时还需要一个小的二进制文件,那么最好完全放弃CRT,并且尽可能只使用Win32 API函数。您仍然会得到一些CRT代码,最明显的是与启动(即调用
main
)和关闭(
atexit
处理等)相关的代码,但否则链接器不会链接您不使用的CRT函数

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

如果您选择后一种方法,您可能还必须处理编译器内部函数的问题。有些函数名义上由CRT定义(并在其标题中声明),但编译器会对其进行特殊处理,以便尽可能在调用点插入优化的汇编指令-例如
memset
strlen
,以及
中的大量函数;可以找到完整的列表。由于您没有CRT,如果您需要这些函数,或者可以避免这些函数,但由于性能的提高(例如,很难比
memset
做得更好)而选择内部函数,那么您必须自己声明它们,并使用
#pragma-instructive
。例如:

// 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;
}

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

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

如果您选择后一种方法,您可能还必须处理编译器内部函数的问题。有些函数名义上由CRT定义(并在其标题中声明),但编译器会对其进行特殊处理,以便尽可能在调用点插入优化的汇编指令-例如
memset
strlen
,以及
中的大量函数;可以找到完整的列表。由于您没有CRT,如果您需要这些函数,或者可以避免这些函数,但由于性能的提高(例如,很难比
memset
做得更好)而选择内部函数,那么您必须自己声明它们,并使用
#pragma-instructive
。例如:

// 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;
}

我认为一种方法是不使用VisualStudio,而是依赖命令行SDK工具。(你也可以考虑如何配置VS来做你想做的事情,但这似乎很难。)例如:


我认为这样做的一个方法就是不使用V
cl /c app.cpp
link app.obj ws2_32.lib