c ++ win32 empêche l’application de s’exécuter sur Windows XP

J’ai développé une application qui utilise des API Vista (ou supérieures) et j’aimerais append un message contextuel si l’application détecte un système d’exploitation non pris en charge.

Je voudrais append un message contextuel lorsqu’un utilisateur exécute mon application sur Windows XP. Actuellement, l’application lance simplement une fenêtre contextuelle (messageBox) indiquant que certains fichiers DLL ne peuvent pas être chargés.

J’ai défini la version Windows comme ceci:

#define _WIN32_WINNT 0x0600 

Que dois-je faire pour empêcher l’exécution sur des versions inférieures à Vista? Dois-je vérifier la version du système d’exploitation lorsque l’application démarre (et afficher un message à l’utilisateur)?

Pour afficher un message contextuel, vous devez exécuter l’exécutable. Cela signifie que vous devez réduire votre version de Windows à la version la plus basse que vous avez l’intention de “prendre en charge” (le support ici signifie pouvoir s’exécuter et afficher une fenêtre contextuelle indiquant qu’il ne s’exécutera pas). Cela nécessiterait que vous retardiez le point si vous aviez un lien vers vos DLL pertinentes, sinon elles ne seraient pas trouvées et vous auriez toujours la même boîte de message que vous connaissez.

Globalement, cette approche présente de nombreux inconvénients, car vous devez créer un exécutable valide à la fois sur XP et sur Vista. Si vous avez vraiment besoin de cette vérification, vous pouvez en faire un exécutable et décider d’afficher un message contextuel ou de lancer votre application (dans un autre exécutable).

Si vous utilisez des API qui ne sont pas disponibles sur XP, vous devrez séparer votre application dans un chargeur et l’application réelle (ou un chargeur et une DLL contenant l’application réelle). Comstackz le chargeur avec #define _WIN32WINNT 0x0501 pour vous assurer qu’il peut s’exécuter sur XP et afficher votre popup.

Vérifiez la version avec VerifyVersionInfo ou GetVersionEx

Vous pouvez écrire une application wrapper très petite qui définit _WIN32_WINNT comme étant 0x0501. Ensuite, ce programme peut faire une vérification du système d’exploitation et afficher une interface utilisateur pour votre utilisateur (si la version de Windows est incorrecte) ou simplement lancer votre autre exécutable (s’il s’agit d’une version de Windows prise en charge).

Idéalement, votre canal de dissortingbution (site Web, etc.) vérifierait que l’utilisateur dispose d’une version prise en charge de Windows avant de lui permettre de le télécharger.

Si vous utilisez WiX (ou MSI directement) pour installer votre application, vous pouvez laisser le programme d’installation gérer la vérification du système d’exploitation non prise en charge.

Vous ne pouvez pas vous attendre à un comportement d’exécution dynamic si vous appliquez un comportement de compilation statique. Vous devez définir la version Windows de XP pour que votre exe soit lié aux DLL XP, puis à l’exécution vous devez modifier le comportement de manière dynamic et charger les DLL Vista et rechercher les points d’entrée «manuellement». Ceci est, comme vous vous en doutez, douloureux et sujet aux erreurs. Bonne chance.

Vous pouvez définir _WIN32_WINNT à une valeur inférieure, appropriée pour 2000 ou XP. Mais alors vous devrez utiliser un lien explicite pour les API de Vista uniquement. La modification de _WIN32_WINNT entraînera également des déclarations de type manquantes pour les API Vista uniquement. Donc, si vous connaissez les API dont vous avez besoin, vous pouvez laisser _WIN32_WINNT à 0x0600 et utiliser un lien explicite pour ces API. De toute évidence, vous aurez également besoin d’une vérification de version pour donner un message utile à l’utilisateur.

Personnellement, je prendrais un autre chemin pour résoudre ce problème. Je vérifierais la version au moment de l’installation et la bloquerais là. Cela vous permet de continuer avec _WIN32_WINNT 0x0600 et toutes les commodités qui permettent.

Ce qui se passe, c’est que les DLL sont chargées par le chargeur d’application et que vous voyez les messages d’erreur avant même que votre application ne démarre. Vous devez empêcher cela.

Vous pouvez placer votre application dans une DLL et créer un programme de remplacement qui effectue la vérification du système d’exploitation, comme décrit Mystical dans sa réponse.

Modifier:

Il semble que Mystical ait supprimé sa réponse … Faites quelque chose comme ceci:

 OSVERSIONINFO OSversion; OSversion.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); ::GetVersionEx(&OSversion); switch(OSversion.dwPlatformId) { case VER_PLATFORM_WIN32_NT: if(OSversion.dwMajorVersion >= 6) { // Yay, load the DLL and call entry point } default: // Show unsupported OS message } 

Vous pouvez appeler LoadLibrary() pour charger votre DLL d’application, puis appeler le point d’entrée que vous avez défini.

Notez que cette réponse contient une liste intéressante des numéros de version du système d’exploitation.

Je ne sais pas comment faire cela dans Visual Studio ou d’autres compilateurs, mais dans les IDE Borland / CodeGear / Embarcadero, il existe une option pour définir la version minimale du système d’exploitation pris en charge dans l’en-tête PE de l’exécutable compilé. Si le chargeur du système d’exploitation tente d’exécuter un exécutable avec une version incompatible, il n’exécutera pas l’exécutable et affichera un message d’erreur à propos de la non-concordance de version. Vérifiez si votre compilateur / IDE dispose d’une option similaire.

Sinon, vous devez charger dynamicment les API souhaitées au moment de l’exécution via LoadLibrary() / GetModuleHandle() et GetProcAddress() au lieu de les lier de manière statique au moment de la compilation. Vous pouvez ensuite effectuer vos propres vérifications de version de système d’exploitation dans votre code avant d’utiliser les nouvelles fonctions de l’API qui peuvent ne pas être disponibles.