用VS7编写的C程序使用Win7 / 8 / 2008R2 / 2012,但不是2003 / XP / 32bit?

我必须首先说我是一个编程菜鸟。 我不了解IDE的所有编译器选项或细微差别,而不是远视。 但我正在尝试更多地了解本机编程语言。 (我对C#很体面,但是这比我发现的容易得多。)

今天,我用C编写了这个小程序。它是一个控制台/命令行程序。 我使用Visual Studio 2012,我的开发机器在Windows 7和8,64位之间交替使用。 首先,我所做的是创建一个新的VC ++项目,然后我选择了一个空白项目。 然后我创建了一个新的app.c文件。 我还创建了一个* .rc文件,当您在Windows资源管理器中浏览文件属性时,为可执行文件提供一些额外的属性,如“文件版本”和“公司名称”。 然后我去了项目的属性,选择了配置属性 – > C / C ++ – >代码生成,我将运行时库更改为“multithreading(/ MT),这样我就不必分发msvcr100.dll文件了以及我的可执行文件。

在app.c文件中,我放置了以下代码:

#include  #include  #include  #include  #pragma comment(lib, "WtsApi32.lib") void main(int argc, char *argv[]) { char *helpMsg = "blah"; char *hostName, *connState = ""; char *addrFamily = ""; HANDLE hHost = NULL; ...stuff and so forth and so on... } 

然后我构建/编译了程序,并且可执行文件在Windows 7,8,Server 2008R2,Server 2012,所有64位上运行正常。 但是当我尝试在Server 2003上运行该程序时(我也猜测WinXP等),我会看到Windows对话框:

“Foo.exe不是有效的Win32应用程序。”

所以我的问题是,是否有一些显而易见/简单的东西,我将丢失,这将允许这个可执行文件也可以在我错过的早期XP / 2003 / 32bit平台上工作? 我不相信我在我的程序中使用任何64位独占function。 但我认为,因为我选择“空白项目”而不是“Win32控制台应用程序”,我可能会错过一些设置。

编辑:这是针对我的exe运行时的dumpbin.exe / headers输出:

 Microsoft (R) COFF/PE Dumper Version 11.00.50727.1 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file C:\users\me\Release\foo.exe PE signature found File Type: EXECUTABLE IMAGE FILE HEADER VALUES 14C machine (x86) 5 number of sections 50F604BC time date stamp Tue Jan 15 19:39:08 2013 0 file pointer to symbol table 0 number of symbols E0 size of optional header 102 characteristics Executable 32 bit word machine OPTIONAL HEADER VALUES 10B magic # (PE32) 11.00 linker version 7800 size of code A200 size of initialized data 0 size of uninitialized data 16A7 entry point (004016A7) _mainCRTStartup 1000 base of code 9000 base of data 400000 image base (00400000 to 00414FFF) 1000 section alignment 200 file alignment 6.00 operating system version 0.00 image version 6.00 subsystem version 0 Win32 version 15000 size of image 400 size of headers 0 checksum 3 subsystem (Windows CUI) 8140 DLL characteristics Dynamic base NX compatible Terminal Server Aware 100000 size of stack reserve 1000 size of stack commit 100000 size of heap reserve 1000 size of heap commit 0 loader flags 10 number of directories 0 [ 0] RVA [size] of Export Directory D374 [ 3C] RVA [size] of Import Directory 11000 [ 538] RVA [size] of Resource Directory 0 [ 0] RVA [size] of Exception Directory 0 [ 0] RVA [size] of Certificates Directory 12000 [ C04] RVA [size] of Base Relocation Directory 9160 [ 38] RVA [size] of Debug Directory 0 [ 0] RVA [size] of Architecture Directory 0 [ 0] RVA [size] of Global Pointer Directory 0 [ 0] RVA [size] of Thread Storage Directory CF98 [ 40] RVA [size] of Load Configuration Directory 0 [ 0] RVA [size] of Bound Import Directory 9000 [ 118] RVA [size] of Import Address Table Directory 0 [ 0] RVA [size] of Delay Import Directory 0 [ 0] RVA [size] of COM Descriptor Directory 0 [ 0] RVA [size] of Reserved Directory SECTION HEADER #1 .text name 7670 virtual size 1000 virtual address (00401000 to 0040866F) 7800 size of raw data 400 file pointer to raw data (00000400 to 00007BFF) 0 file pointer to relocation table 0 file pointer to line numbers 0 number of relocations 0 number of line numbers 60000020 flags Code Execute Read SECTION HEADER #2 .rdata name 49E2 virtual size 9000 virtual address (00409000 to 0040D9E1) 4A00 size of raw data 7C00 file pointer to raw data (00007C00 to 0000C5FF) 0 file pointer to relocation table 0 file pointer to line numbers 0 number of relocations 0 number of line numbers 40000040 flags Initialized Data Read Only Debug Directories Time Type Size RVA Pointer -------- ------ -------- -------- -------- 50F604BC cv 61 0000CFE0 BBE0 Format: RSDS, {582D0FF2-59C1-4633-AF2A-E4A4AD6BFA2C}, 1, C:\Users\me\Release\users.pdb 50F604BC feat 10 0000D044 BC44 Counts: Pre-VC++ 11.00=0, C/C++=116, /GS=116, /sdl=0 SECTION HEADER #3 .data name 2C04 virtual size E000 virtual address (0040E000 to 00410C03) E00 size of raw data C600 file pointer to raw data (0000C600 to 0000D3FF) 0 file pointer to relocation table 0 file pointer to line numbers 0 number of relocations 0 number of line numbers C0000040 flags Initialized Data Read Write SECTION HEADER #4 .rsrc name 538 virtual size 11000 virtual address (00411000 to 00411537) 600 size of raw data D400 file pointer to raw data (0000D400 to 0000D9FF) 0 file pointer to relocation table 0 file pointer to line numbers 0 number of relocations 0 number of line numbers 40000040 flags Initialized Data Read Only SECTION HEADER #5 .reloc name 235C virtual size 12000 virtual address (00412000 to 0041435B) 2400 size of raw data DA00 file pointer to raw data (0000DA00 to 0000FDFF) 0 file pointer to relocation table 0 file pointer to line numbers 0 number of relocations 0 number of line numbers 42000040 flags Initialized Data Discardable Read Only Summary 3000 .data 5000 .rdata 3000 .reloc 1000 .rsrc 8000 .text 

我也试过去Project Properties – > Linker – > System:Minimum Required Version并将其改为5.00和1.00或者其他什么,但它没有效果。 dumpbin.exe仍然将操作系统版本报告为6.00。 我甚至在exe上使用了editbin.exe / version 5.00并且没有报告错误…但是dumpbin.exe仍然报告操作系统版本为6.00。

VS2012最初出货时没有支持XP / 2003。 更新的CRT和运行时支持库使用的太多Windows api函数在这些操作系统上不可用。 这引起了客户的极大轰动,温和地说,并且他们重​​新设计了库以动态地绑定到这些function并且沿着它丢失它们。 这在Update 1中可用,您需要使用Project + Properties,General, Platform Toolset = v110_xp来构建使用这些库的程序。

请注意它如何更改链接器设置,重要的是链接器>系统>最低要求版本=“5.01”。 这确保可执行文件被标记为与XP子系统版本兼容。 您还将针对SDK版本7.1构建,最后一个版本仍与XP兼容。

当您使用默认工具集(v110)时,您将目标指向子系统6.00和SDK版本8.版本6.00是最后一个主要的内核版本,从Vista开始。

新的api函数的简要概述用于给你一个(非常粗略的)想法XP版本中缺少的内容:

  • FlsAlloc,FlsFree,FlsGetValue,FlsSetValue:安全的线程本地存储
  • InitializeCriticalSectionEx,CreateSemaphoreEx:安全
  • SetThreadStackGuarantee:稳定性
  • CreateThreadPoolTimer,SetThreadPoolTimer,W​​aitForThreadPoolTimerCallbacks,CloseThreadPoolTimer:更便宜的计时器
  • CreateThreadPoolWait,SetThreadPoolWait,CloseThreadPoolWait:更便宜的等待?
  • FlushProcessWriteBuffers,GetCurrentProcessorNumber,GetLogicalProcessorInformation:threading
  • FreeLibraryWhenCallbackReturns:稳定性?
  • CreateSymbolicLink:function
  • InitOnceExecuteOnce:未知
  • SetDefaultDllDirectories:未知
  • EnumLocalesEx,CompareStringEx,GetDateFormatEx,GetLocalInfoEx,GetTimeFormatEx,GetUserDefaultLocaleName,IsValidLocaleName,LCMapStringEx:更好的语言环境支持

我自己弄清楚了。 (但是谢谢Hans让我指导正确的方向。)出于某种原因,即使使用Update 1,甚至在将我的工具集设置为v110_xp, 在Linker选项中将所需的最低版本设置为5.01之后,生成的dumpbin app.exe /headers仍然报告最低操作系统版本6.0。

所以我只是跑了

 editbin.exe app.exe /SUBSYSTEM:CONSOLE,5.01 /OSVERSION:5.1 

现在,可执行文件在较旧的操作系统上运行良好。 我在想Visual Studio中某处可能还有一点bug。

MSVC团队博客说,当使用命令行中的MSBuild或DEVENV与v110_xp平台工具集时,不需要进行其他更改。 此信息不正确/不完整。 还必须适当地设置/ SUBSYSTEM链接器参数和关联的“Minimum Required Version”。

/ ENTRY的MSDN文档指出,如果未指定/ SUBSYSTEM参数,则自动确定SUBSYSTEM和ENTRY POINT。 我的预感是,当发生这种情况时,SUBSYSTEM的“最低要求版本”参数也会自动被覆盖。

v110_xp工具集自动指定SUBSYSTEM的MRV(“5.1”(WindowsXP)),但不指定SUBSYSTEM。 因此,例如,链接器将覆盖MRV到“6.0”。 然后,运行该应用程序将导致WindowsXP显示错误消息,指出该应用程序“不是有效的Win32应用程序”。