Я знаю, что этот вопрос задавался раньше, но я до сих пор не получил удовлетворительного ответа или однозначного «нет, это невозможно», поэтому я спрошу еще раз!
Все, что я хочу сделать, это получить путь к исполняемому файлу, запущенному в данный момент, либо в виде абсолютного пути, либо относительно того, откуда этот исполняемый файл вызывается, независимо от платформы. Я думал, что boost :: filesystem :: initial_path был ответом на мои проблемы, но, похоже, он обрабатывает только «платформенно-независимую» часть вопроса - он по-прежнему возвращает путь, из которого было вызвано приложение.
Для некоторой предыстории, это игра с использованием Ogre, которую я пытаюсь профилировать с помощью Very Sleepy, которая запускает целевой исполняемый файл из своего собственного каталога, поэтому, конечно, при загрузке игра не находит файлов конфигурации и т. Д. И сразу вылетает. . Я хочу иметь возможность передать ему абсолютный путь к файлам конфигурации, которые, как я знаю, всегда будут находиться рядом с исполняемым файлом. То же самое касается отладки в Visual Studio - я бы хотел иметь возможность запускать $ (TargetPath) без необходимости устанавливать рабочий каталог.
источник
Ответы:
Я не знаю кроссплатформенного способа.
Для Linux: readlink / proc / self / exe
Windows: GetModuleFileName
источник
Функция boost :: dll :: program_location - один из лучших кроссплатформенных методов получения пути к исполняемому файлу, о котором я знаю. Библиотека DLL была добавлена в Boost в версии 1.61.0.
Вот мое решение. Я тестировал его в Windows, Mac OS X, Solaris, Free BSD и GNU / Linux.
Требуется Boost 1.55.0 или выше. Он использует библиотеку Boost.Filesystem непосредственно и Boost.Locale библиотеку и Boost.System библиотеку косвенно.
SRC / исполняемый_путь.cpp
SRC / деталь / исполняемый_путь_internals.cpp
включить / boost / исполняемый_путь.hpp
включить / boost / detail / исполняемый_путь_internals.hpp
У меня есть полный проект, включая тестовое приложение и файлы сборки CMake, доступные в SnKOpen - / cpp / executable_path / trunk . Эта версия более полная, чем версия, которую я предоставил здесь. Он также поддерживает больше платформ.
Я протестировал приложение на всех поддерживаемых операционных системах в следующих четырех сценариях.
Во всех четырех сценариях обе функции executable_path и executable_path_fallback работают и возвращают одинаковые результаты.
Ноты
Это обновленный ответ на этот вопрос. Я обновил ответ, чтобы учесть комментарии и предложения пользователей. Я также добавил ссылку на проект в моем репозитории SVN.
источник
argv[0]
также может быть просто исполняемым именем, и в этом случае его необходимо будет искать вPATH
системах * nix.Этот способ использует boost + argv. Вы упомянули, что это не может быть кросс-платформенный, потому что он может включать или не включать имя исполняемого файла. Следующий код должен обойти это.
Следующий код получает текущий рабочий каталог, который может делать то, что вам нужно.
Примечание. Только что понял, что
basename(
) устарел, поэтому пришлось переключиться на.stem()
источник
.parent_path()
, нет.stem()
, нет?@Claudiu
сказал, думаю, так и должно быть.parent_path()
.Я не уверен насчет Linux, но попробуйте это для Windows:
источник
WCHAR ownPth..
, обернутый вокруг a,#ifdef UNICODE
если он компилируется с поддержкой Unicode. Если нет, используйте предоставленный код.HMODULE hModule = GetModuleHandle(NULL);
C ++ 17, windows, unicode, с использованием нового API файловой системы:
Подозреваю, что это решение должно быть переносимым, но не знаю, как реализован Unicode в других ОС.
weakly_canonical требуется только в том случае, если вы используете в качестве ссылок на верхнюю папку выходного каталога ('..') для упрощения пути. Если не пользуетесь - удалите.
Если вы работаете из библиотеки динамической компоновки (.dll /.so), тогда у вас может не быть argv, тогда вы можете рассмотреть следующее решение:
application.h:
application.cpp:
источник
Для окон:
GetModuleFileName
- возвращает путь exe + имя файла exeЧтобы удалить имя файла
PathRemoveFileSpec
источник
This function is deprecated. We recommend the use of the PathCchRemoveFileSpec function in its place
.QT предоставляет это с абстракцией ОС как QCoreApplication :: applicationDirPath ()
источник
QCoreApplication::applicationDirPath: Please instantiate the QApplication object first
. Есть идеи, как это решить?QCoreApplication
как такQApplication application(argc, argv);
(сделать это вmain(argc, argv)
, и быть уверенным , что вы не изменяетеargc/argv
, так как они должны оставаться в силе в течение всего срока службы QCoreApplication (проверьте документацию )Это специфичный для Windows способ, но это как минимум половина вашего ответа.
GetThisPath.h
GetThisPath.cpp
mainProgram.cpp
Я бы предложил использовать определение платформы в качестве директив препроцессора, чтобы изменить реализацию функции-оболочки, которая вызывает
GetThisPath
для каждой платформы.источник
Используя args [0] и ищите '/' (или '\\'):
EDITED: если '/' не существует, pos == - 1, поэтому результат правильный.
источник
args[0]
может вообще не быть путем.args[0]
беспокоит то, что это не обязательно путь к исполняемому файлу. Тем не менее, спасибо за исправление вашего ответа для Windows :)Для Windows вы можете использовать GetModuleFilename ().
Для Linux см.
BinReloc (старый, несуществующий URL)зеркало BinReloc в репозиториях datenwolf на GitHub .источник
Следующее работает как быстрое и грязное решение, но учтите, что оно далеко не надежно:
источник
Если вам нужно обрабатывать пути Unicode для Windows:
источник
Для Windows у вас есть проблема, как удалить исполняемый файл из результата
GetModuleFileName()
. Вызов Windows API,PathRemoveFileSpec()
который Нейт использовал для этой цели в своем ответе, изменился между Windows 8 и ее предшественниками. Итак, как оставаться совместимым и безопасным? К счастью, есть C ++ 17 (или Boost, если вы используете более старый компилятор). Я сделаю это:источник
Как уже упоминалось,
argv[0]
это довольно хорошее решение при условии, что платформа фактически передает исполняемый путь, что, безусловно, не менее вероятно, чем ОС, являющаяся Windows (где WinAPI может помочь найти исполняемый путь). Если вы хотите разделить строку, чтобы включить только путь к каталогу, в котором находится исполняемый файл, то использование этого пути для поиска других файлов приложения (например, игровых ресурсов, если ваша программа является игрой) совершенно нормально, поскольку открытие файлов происходит относительно рабочий каталог или, если он есть, корень.источник
Вот что у меня получилось
Заголовочный файл выглядит так:
Реализация
источник
Библиотека SDL2 ( https://www.libsdl.org/ ) имеет две функции, реализованные на широком спектре платформ:
Так что, если вы не хотите изобретать велосипед ... к сожалению, это означает включение всей библиотеки, хотя у нее есть довольно разрешительная лицензия, и можно также просто скопировать код. Кроме того, он предоставляет множество других кроссплатформенных функций.
источник
Вероятно, это наиболее естественный способ сделать это, охватывающий большинство основных настольных платформ. Я не уверен, но я считаю, что это должно работать со всеми BSD, а не только с FreeBSD, если вы измените проверку макроса платформы, чтобы охватить их все. Если мне удастся установить Solaris, я обязательно добавлю эту платформу в список поддерживаемых.
Имеет полную поддержку UTF-8 в Windows, что не всем важно, чтобы зайти так далеко.
procinfo / win32 / procinfo.cpp
procinfo / macosx / procinfo.cpp
procinfo / linux / procinfo.cpp
procinfo / freebsd / procinfo.cpp
procinfo / procinfo.cpp
procinfo / procinfo.h
Это позволяет получить полный путь к исполняемому файлу практически любого идентификатора процесса, за исключением того, что в Windows есть некоторые процессы с атрибутами безопасности, которые просто не позволяют этого, поэтому wysiwyg, это решение не идеально.
Чтобы более точно ответить на вопрос, вы можете сделать это:
procinfo.cpp
Создайте указанную выше файловую структуру с помощью этой команды:
procinfo.sh
Для загрузки копии файлов, перечисленных выше:
Для получения дополнительной информации о кросс-платформенных процессах:
https://github.com/time-killer-games/enigma-dev
Ознакомьтесь с файлом readme для получения списка большинства включенных функций.
источник
При использовании C ++ 17 можно сделать следующее, чтобы получить путь к исполняемому файлу.
Приведенный выше ответ был протестирован на Debian 10 с использованием G ++ 9.3.0.
источник
Это было моим решением в Windows. Он называется так:
Где 64 - это минимальный размер, по вашему мнению, будет путь. GetPathOfEXE вызывает себя рекурсивно, каждый раз удваивая размер буфера, пока он не получит достаточно большой буфер, чтобы получить весь путь без усечения.
источник
new
и (неправильного)delete
? Если бы вы использовали astd::vector
, ваш код не показал бы неопределенного поведения.GetModuleFileNameW
в случае успеха не устанавливает последний код ошибки. Этот код сломан по-разному. Не используйте, если случайно наткнетесь на это.Начиная с C ++ 17:
Убедитесь, что вы включили файловую систему std.
и теперь ты можешь это сделать.
файловая система boost стала частью стандартной библиотеки lib.
если вы не можете найти его, попробуйте заглянуть в:
источник
источник
PathRemoveFileSpec()
Вместо этого взгляните на и связанные функции.в Unix (включая Linux) попробуйте "which", в Windows попробуйте "where".
источник
Этот метод работает как для Windows, так и для Linux:
источник