Programme C écrit dans VS2012 Works avec Win7 / 8 / 2008R2 / 2012, mais pas 2003 / XP / 32bit?

Je dois commencer par dire que je suis vraiment un noob en programmation. Je ne comprends pas toutes les options du compilateur ni les nuances de l’EDI, pas par une longue vue. Mais j’essaie de m’apprendre davantage sur les langages de programmation natifs. (Je suis décent avec C #, mais c’est beaucoup plus facile que C, comme je le découvre.)

Aujourd’hui, j’ai écrit ce petit programme en C. Il s’agit d’un programme en ligne de commande / console. J’ai utilisé Visual Studio 2012 et ma machine de développement alterne entre Windows 7 et 8, 64 bits. Pour commencer, j’ai créé un nouveau projet VC ++ et j’ai choisi un projet vierge. Ensuite, j’ai créé un nouveau fichier app.c. J’ai également créé un fichier * .rc pour donner à l’exécutable des propriétés supplémentaires telles que “Version du fichier” et “Nom de la société” lorsque vous parcourez les propriétés du fichier dans l’Explorateur Windows. Ensuite, je suis allé dans les propriétés du projet, j’ai choisi Propriétés de configuration -> C / C ++ -> Génération de code et j’ai changé la bibliothèque d’exécution en “Multi-threaded (/ MT)” pour ne pas avoir à dissortingbuer le fichier msvcr100.dll avec mon exécutable.

Dans le fichier app.c, j’ai placé le code suivant:

#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... } 

Ensuite, j’ai construit / compilé le programme, et l’exécutable fonctionne parfaitement sous Windows 7, 8, Server 2008R2, Server 2012, tous 64 bits. Mais lorsque j’essaie d’exécuter le programme sur Server 2003 (et je devine aussi WinXP, etc.), je suis accueilli par la boîte de dialog Windows:

“Foo.exe n’est pas une application Win32 valide.”

Ma question est donc la suivante: y at-il quelque chose d’évident / simple qui me manque qui permettrait à cet exécutable de fonctionner également sur les plates-formes XP / 2003 / 32bit antérieures qui me manquent? Je ne crois pas que j’utilise des fonctionnalités exclusives 64 bits dans mon programme. Mais j’ai pensé que depuis que j’avais choisi “Projet vide” au lieu de “Application console Win32”, certains parameters pouvaient me manquer.

Edit: Voici la sortie de dumpbin.exe / headers lorsqu’elle est exécutée sur mon exe:

 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 

J’ai également essayé d’aller dans les propriétés du projet -> Éditeur de liens -> Système: Version minimale requirejse et de changer cela en versions 5.00 et 1.00, etc., mais cela n’a aucun effet. dumpbin.exe signale toujours la version du système d’exploitation sous la forme 6.00. J’ai même utilisé editbin.exe / version 5.00 sur l’exe et aucune erreur n’a été signalée … et pourtant, dumpbin.exe signale toujours 6,00 pour la version du système d’exploitation.

VS2012 à l’origine expédié sans support XP / 2003. Les bibliothèques de support CRT et d’exécution mises à jour utilisent trop de fonctions de l’API Windows qui ne sont pas disponibles sur ces systèmes d’exploitation. Cela a provoqué une certaine agitation parmi ses clients, et c’est peu dire, et ils ont repensé les bibliothèques pour qu’elles se lient dynamicment à ces fonctions et boivent le long de leur absence. Ceci a été rendu disponible dans la mise à jour 1 ; vous devez utiliser Project + Properties, General, Platform Toolset = v110_xp pour créer des programmes utilisant ces bibliothèques.

Notez comment cela modifie un paramètre de l’éditeur de liens, l’important, Éditeur de liens> Système> Version minimale requirejse = “5.01”. Ce qui garantit que le fichier exécutable est marqué pour être compatible avec la version du sous-système XP. Vous construirez également contre le SDK version 7.1, le dernier compatible avec XP.

Lorsque vous utilisez le jeu d’outils par défaut (v110), vous ciblez le sous-système 6.00 et le SDK version 8. La version 6.00 était la dernière révision majeure du kernel, démarrée avec Vista.

Un bref aperçu des nouvelles fonctions de l’API utilisées pour vous donner une idée (très approximative) de ce qui manque dans la version XP:

  • FlsAlloc, FlsFree, FlsGetValue, FlsSetValue: stockage de thread local sécurisé
  • InitializeCriticalSectionEx, CreateSemaphoreEx: sécurité
  • SetThreadStackGu warranty: stabilité
  • CreateThreadPoolTimer, SetThreadPoolTimer, WaitForThreadPoolTimerCallbacks, CloseThreadPoolTimer: timers moins chères
  • CreateThreadPoolWait, SetThreadPoolWait, CloseThreadPoolWait: des attentes moins chères?
  • FlushProcessWriteBuffers, GetCurrentProcessorNumber, GetLogicalProcessorInformation: threading
  • FreeLibraryWhenCallbackReturns: stabilité?
  • CreateSymbolicLink: fonctionnalité
  • InitOnceExecuteOnce: inconnu
  • SetDefaultDllDirectories: inconnu
  • EnumLocalesEx, CompareSsortingngEx, GetDateFormatEx, GetLocalInfoEx, GetTimeFormatEx, GetUserDefaultLocaleName, IsValidLocaleName, LCMapSsortingngEx: meilleure prise en charge des parameters régionaux

Je l’ai compris moi-même. (Mais merci Hans de m’avoir orienté dans la bonne direction.) Pour une raison quelconque, même avec la mise à jour 1 et même après avoir défini mon jeu d’outils sur v110_xp et défini la version minimale requirejse sur 5.01 dans les options de l’ dumpbin app.exe /headers , le dumpbin app.exe /headers signale toujours une version minimale du système d’exploitation de 6.0.

Alors j’ai simplement couru

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

Et l’exécutable fonctionne parfaitement sur les anciens systèmes d’exploitation. Je pense qu’il pourrait toujours y avoir un petit problème quelque part dans Visual Studio.

Le blog de l’équipe MSVC indique que, lorsque vous utilisez MSBuild ou DEVENV à partir de la ligne de commande avec le jeu d’outils de la plate-forme v110_xp, aucun autre changement n’est nécessaire. Cette information est incorrecte / incomplète. L’argument de l’éditeur de liens / SUBSYSTEM et la “version minimale requirejse” associé doivent également être définis de manière appropriée.

La documentation MSDN pour / ENTRY indique que, si l’argument / SUBSYSTEM n’est pas spécifié, le sous-système et le point d’entrée sont déterminés automatiquement. Mon intuition est que, lorsque cela se produit, l’argument “Version minimale requirejse” du SUBSYSTEM est également automatiquement remplacé.

Le jeu d’outils v110_xp spécifie automatiquement le MRV du SUBSYSTEM (“5.1” (Windows XP)) mais pas le SUBSYSTEM. En tant que tel, le MRV sera remplacé, par exemple, par l’éditeur de liens en “6.0”. Si vous exécutez l’application, Windows XP affichera alors le message d’erreur indiquant que l’application “n’est pas une application Win32 valide”.