Je sais que cette question a déjà été posée mais je n'ai toujours pas vu de réponse satisfaisante, ou un "non, cela ne peut pas être fait", alors je vais demander à nouveau!
Tout ce que je veux faire, c'est obtenir le chemin d'accès à l'exécutable en cours d'exécution, soit en tant que chemin absolu, soit par rapport à l'endroit d'où l'exécutable est appelé, d'une manière indépendante de la plate-forme. Je pensais que boost :: filesystem :: initial_path était la réponse à mes problèmes, mais cela ne semble gérer que la partie «indépendante de la plate-forme» de la question - il renvoie toujours le chemin à partir duquel l'application a été appelée.
Pour un peu de contexte, il s'agit d'un jeu utilisant Ogre, que j'essaie de profiler en utilisant Very Sleepy, qui exécute l'exécutable cible à partir de son propre répertoire, donc bien sûr, lors du chargement, le jeu ne trouve aucun fichier de configuration, etc. et se bloque rapidement. . Je veux pouvoir lui transmettre un chemin absolu vers les fichiers de configuration, qui, je le sais, vivront toujours avec l'exécutable. Il en va de même pour le débogage dans Visual Studio - j'aimerais pouvoir exécuter $ (TargetPath) sans avoir à définir le répertoire de travail.
la source
Réponses:
Il n'y a aucun moyen multiplateforme que je connaisse.
Pour Linux: readlink / proc / self / exe
Windows: GetModuleFileName
la source
Le boost :: dll :: program_location est l'une des meilleures méthodes multiplateformes pour obtenir le chemin de l'exécutable en cours d'exécution que je connaisse. La bibliothèque DLL a été ajoutée à Boost dans la version 1.61.0.
Voici ma solution. Je l'ai testé sur Windows, Mac OS X, Solaris, Free BSD et GNU / Linux.
Il nécessite Boost 1.55.0 ou supérieur. Il utilise la bibliothèque Boost.Filesystem directement et la Boost.Locale bibliothèque et Boost.System bibliothèque indirectement.
src / chemin_exécutable.cpp
src / detail / executable_path_internals.cpp
include / boost / executable_path.hpp
include / boost / detail / executable_path_internals.hpp
J'ai un projet complet, y compris une application de test et des fichiers de construction CMake disponibles sur SnKOpen - / cpp / executable_path / trunk . Cette version est plus complète que la version que j'ai fournie ici. Il prend également en charge plus de plates-formes.
J'ai testé l'application sur tous les systèmes d'exploitation pris en charge dans les quatre scénarios suivants.
Dans les quatre scénarios, les fonctions executable_path et executable_path_fallback fonctionnent et renvoient les mêmes résultats.
Remarques
Ceci est une réponse mise à jour à cette question. J'ai mis à jour la réponse pour prendre en compte les commentaires et suggestions des utilisateurs. J'ai également ajouté un lien vers un projet dans mon référentiel SVN.
la source
argv[0]
peut également être simplement un nom d'exécutable, auquel cas il serait nécessaire de le rechercher dansPATH
les systèmes * nix.Cette façon utilise boost + argv. Vous avez mentionné que cela peut ne pas être multiplateforme car il peut inclure ou non le nom de l'exécutable. Eh bien, le code suivant devrait contourner ce problème.
Le code suivant obtient le répertoire de travail actuel qui peut faire ce dont vous avez besoin
Remarque Je viens de me rendre compte que
basename(
) était obsolète et a donc dû passer à.stem()
la source
.parent_path()
, non.stem()
, non?@Claudiu
je l'ai dit, je pense que cela devrait l'être.parent_path()
.Je ne suis pas sûr de Linux, mais essayez ceci pour Windows:
la source
WCHAR ownPth..
, encapsulé autour d'un#ifdef UNICODE
dans le cas où l'on compile avec le support Unicode. Sinon, utilisez le code fourni.HMODULE hModule = GetModuleHandle(NULL);
Pour les fenêtres:
GetModuleFileName
- renvoie le chemin exe + le nom du fichier exePour supprimer le nom de fichier
PathRemoveFileSpec
la source
This function is deprecated. We recommend the use of the PathCchRemoveFileSpec function in its place
.C ++ 17, Windows, Unicode, en utilisant la nouvelle API du système de fichiers:
Je pense que cette solution devrait être portable, mais je ne sais pas comment unicode est implémenté sur d'autres systèmes d'exploitation.
lowly_canonical n'est nécessaire que si vous utilisez comme références de dossier supérieur du répertoire de sortie ('..') pour simplifier le chemin. Si vous ne l'utilisez pas, supprimez-le.
Si vous utilisez une bibliothèque de liens dynamiques (.dll /.so), vous n'avez peut-être pas argv, vous pouvez envisager la solution suivante:
application.h:
application.cpp:
la source
QT fournit cela avec l'abstraction du système d'exploitation comme QCoreApplication :: applicationDirPath ()
la source
QCoreApplication::applicationDirPath: Please instantiate the QApplication object first
. Une idée de comment résoudre ça?QCoreApplication
typeQApplication application(argc, argv);
(faites-le dans votremain(argc, argv)
, et assurez-vous de ne pas modifier leargc/argv
, car ceux-ci doivent rester valides pendant toute la durée de vie de QCoreApplication (consultez la documentation )C'est une méthode spécifique à Windows, mais c'est au moins la moitié de votre réponse.
GetThisPath.h
GetThisPath.cpp
mainProgram.cpp
Je suggérerais d'utiliser la détection de plate-forme comme directives de préprocesseur pour modifier l'implémentation d'une fonction wrapper qui appelle
GetThisPath
chaque plate-forme.la source
En utilisant args [0] et en recherchant '/' (ou '\\'):
EDITED: Si '/' n'existe pas, pos == - 1 donc le résultat est correct.
la source
args[0]
ne sera peut - être pas du tout un chemin.args[0]
ne pas nécessairement être le chemin de l'exécutable qui me dérange. Merci d'avoir corrigé votre réponse pour Windows :)Pour Windows, vous pouvez utiliser GetModuleFilename ().
Pour Linux, voir
BinReloc (ancienne URL défunte)miroir de BinReloc dans les référentiels GitHub de datenwolf .la source
Ce qui suit fonctionne comme une solution rapide et sale, mais notez que c'est loin d'être infaillible:
la source
Au cas où vous auriez besoin de gérer les chemins Unicode pour Windows:
la source
Pour Windows, vous avez le problème de savoir comment supprimer l'exécutable du résultat de
GetModuleFileName()
. L'appel de l'API WindowsPathRemoveFileSpec()
que Nate a utilisé à cette fin dans sa réponse a changé entre Windows 8 et ses prédécesseurs. Alors, comment rester compatible avec les deux et en toute sécurité? Heureusement, il existe C ++ 17 (ou Boost, si vous utilisez un compilateur plus ancien). Je fais ça:la source
Comme d'autres l'ont mentionné,
argv[0]
c'est une solution plutôt intéressante, à condition que la plate-forme passe réellement le chemin de l'exécutable, ce qui n'est sûrement pas moins probable que le système d'exploitation Windows (où WinAPI peut aider à trouver le chemin de l'exécutable). Si vous souhaitez supprimer la chaîne pour n'inclure que le chemin du répertoire où réside l'exécutable, alors utiliser ce chemin pour trouver d'autres fichiers d'application (comme les ressources de jeu si votre programme est un jeu) est parfaitement bien, car l'ouverture des fichiers est relative à le répertoire de travail ou, le cas échéant, la racine.la source
C'est ce avec quoi j'ai fini
Le fichier d'en-tête ressemble à ceci:
la mise en oeuvre
la source
La bibliothèque SDL2 ( https://www.libsdl.org/ ) a deux fonctions implémentées sur un large éventail de plates-formes:
Donc, si vous ne voulez pas réinventer la roue ... malheureusement, cela signifie inclure toute la bibliothèque, bien qu'elle ait une licence assez permissive et que l'on puisse aussi simplement copier le code. En outre, il fournit de nombreuses autres fonctionnalités multiplateformes.
la source
C'est probablement la manière la plus naturelle de le faire, tout en couvrant la plupart des principales plates-formes de bureau. Je ne suis pas sûr, mais je pense que cela devrait fonctionner avec tous les BSD, pas seulement FreeBSD, si vous modifiez la vérification des macros de la plate-forme pour les couvrir tous. Si jamais j'arrive à installer Solaris, je veillerai à ajouter cette plate-forme à la liste prise en charge.
Prise en charge complète de UTF-8 sur Windows, ce que tout le monde ne se soucie pas suffisamment pour aller aussi loin.
procinfo / win32 / procinfo.cpp
procinfo / macosx / procinfo.cpp
procinfo / linux / procinfo.cpp
procinfo / freebsd / procinfo.cpp
procinfo / procinfo.cpp
procinfo / procinfo.h
Cela permet d'obtenir le chemin complet vers l'exécutable de quasiment n'importe quel identifiant de processus, sauf sous Windows, il existe des processus avec des attributs de sécurité qui ne le permettront tout simplement pas, donc wysiwyg, cette solution n'est pas parfaite.
Pour répondre plus précisément à ce que la question posait, vous pouvez faire ceci:
procinfo.cpp
Construisez la structure de fichier ci-dessus avec cette commande:
procinfo.sh
Pour télécharger une copie des fichiers répertoriés ci-dessus:
Pour plus de qualité liée aux processus multiplateformes:
https://github.com/time-killer-games/enigma-dev
Voir le readme pour une liste de la plupart des fonctions incluses.
la source
Si vous utilisez C ++ 17, vous pouvez faire ce qui suit pour obtenir le chemin d'accès à l'exécutable.
La réponse ci-dessus a été testée sur Debian 10 en utilisant G ++ 9.3.0
la source
À partir de C ++ 17:
Assurez-vous d'inclure le système de fichiers std.
et maintenant vous pouvez le faire.
Le système de fichiers boost est devenu une partie de la bibliothèque standard.
si vous ne le trouvez pas, essayez de regarder ci-dessous:
la source
C'était ma solution sous Windows. Il s'appelle ainsi:
Où 64 est la taille minimale que vous pensez que le chemin sera. GetPathOfEXE s'appelle lui-même récursivement, doublant la taille du tampon à chaque fois jusqu'à ce qu'il obtienne un tampon suffisamment grand pour obtenir le chemin complet sans troncature.
la source
new
et le (mauvais)delete
? Si vous aviez utilisé astd::vector
, votre code n'aurait pas présenté de comportement indéfini.GetModuleFileNameW
ne définit pas le dernier code d'erreur en cas de succès. Ce code est cassé à bien des égards. Ne l'utilisez pas si vous tombez dessus.la source
PathRemoveFileSpec()
plutôt un œil aux fonctions associées.sous Unix (y compris Linux), essayez «qui», sous Windows, essayez «où».
la source
Cette méthode fonctionne à la fois pour Windows et Linux:
la source