Существует ли метод, не зависящий от платформы и файловой системы, для получения полного пути к каталогу, в котором выполняется программа с использованием C / C++? Не путать с текущим рабочим каталогом. (Пожалуйста, не предлагайте библиотеки, если они не стандартные, например clib или STL.)
(Если нет независимого от платформы / файловой системы метода, приветствуются также предложения, которые работают в Windows и Linux для определенных файловых систем.)
Просто чтобы уточнить: «текущий каталог» или «каталог, из которого запущена программа» (в терминологии вопроса) - это каталог, в котором находится файл изображения программы (файл ~ .exe), и 'текущий каталог работающий' - это каталог, который заполняется автоматически, если программа использует относительные пути?
Когда вы используете #include <windows.h>, Windows автоматически помещает char* в путь к исполняемому файлу в _pgmptr. Вам не нужно вызывать дополнительные функции или предполагать нежелательную загрузку, если вы работаете только в Windows.
Это ответ на ваш первоначальный вопрос? github.com/gpakosz/whereami
Хотя комментарий был сделан три года назад, я хотел бы расширить комментарий rsethc о _pgmptr. В документации MSDN указано, что переменные _pgmptr и _wpgmptr устарели, и вместо них следует использовать функцию _get_pgmptr(char**) или _get_wpgmptr(wchar_t**). MSDN
Я пробовал версию для Windows с использованием Borland C++ Builder 6, параметры pBuf и len не известны. Неопределенный символ. Какие заголовки я должен включить?
Если у вас современный компилятор, вы можете проверить stackoverflow.com/a/60804126/3246135.





Для Win32 GetCurrentDirectory должен помочь.
Есть большой улов с этой функцией: Многопоточные приложения и код разделяемых библиотек не должны использовать функцию GetCurrentDirectory и должны избегать использования относительных путей.. Если вы можете работать с этим предположением, это лучшее решение.
Нет, стандартного способа нет. Я считаю, что стандарты C / C++ даже не рассматривают существование каталогов (или других организаций файловых систем).
В Windows GetModuleFileName () вернет полный путь к исполняемому файлу текущего процесса, если для параметра hModule установлено значение НУЛЕВОЙ. Я не могу помочь с Linux.
Также вы должны уточнить, хотите ли вы текущий каталог или каталог, в котором находится образ программы / исполняемый файл. В настоящее время ваш вопрос немного двусмысленен по этому поводу.
Если вам нужен стандартный способ без библиотек: Нет. Вся концепция каталога не включена в стандарт.
Если вы согласны с тем, что некоторая (переносимая) зависимость от почти стандартной библиотеки допустима: используйте Библиотека файловой системы Boost и запросите initial_path ().
ИМХО, это как можно ближе, с хорошей кармой (Boost - это хорошо зарекомендовавший себя высококачественный набор библиотек)
Из документации Boost: template <class Path> const Path & initial_path (); Возвращает: current_path () во время входа в main (). А current_path () - это «как если бы POSIX getcwd ()». Это не то, что просил вопрошающий.
см. boost.org/doc/libs/1_46_1/libs/filesystem/v3/doc/… для повышения 1.46.1
Как указано в комментариях, это дает путь, откуда был вызван двоичный файл, а не путь к двоичному файлу ... поскольку он может быть запущен из другой папки.
На платформах POSIX вы можете использовать getcwd ().
В Windows вы можете использовать _getcwd (), поскольку использование getcwd () устарело.
Для стандартных библиотек, если бы Boost был для вас достаточно стандартным, я бы предложил Boost :: filesystem, но, похоже, они удалили нормализацию пути из предложения. Возможно, вам придется подождать до TR2 становится доступным, чтобы получить полностью стандартное решение.
getcwd () не выполняет то, что спросил спрашивающий.
Разве в принятом ответе не используется getcwd (), или я просто не понимаю?
Я проголосовал "за", потому что вы первым пришли с тем, что считается правильным ответом.
Этот ответ даже не пытается ответить на вопрос. Стыдно писать это.
Может быть, объединить текущий рабочий каталог с argv [0]? Я не уверен, будет ли это работать в Windows, но это работает в Linux.
Например:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char **argv) {
char the_path[256];
getcwd(the_path, 255);
strcat(the_path, "/");
strcat(the_path, argv[0]);
printf("%s\n", the_path);
return 0;
}
При запуске выводит:
jeremy@jeremy-desktop:~/Desktop$ ./test
/home/jeremy/Desktop/./test
Вам нужно будет проверить, указан ли абсолютный путь в argv [0]. Но что еще более важно, что, если изображение находится через PATH? Заполняет ли linux полный путь или только то, что указано в командной строке?
Как заметил Майк Б., это не общее решение; он работает только в очень ограниченных обстоятельствах. По сути, только когда вы запускаете команду по относительному имени пути - и это не так уж элегантно, когда вы запускаете ../../../bin/progname вместо ./test
Если вы разрешите возможный относительный путь argv [0] по сравнению с текущим каталогом (потому что argv [0] может быть «../../myprogram.exe»), это, вероятно, самый безопасный способ ответить на вопрос. Он всегда будет работать и портативен (работает даже на Android!).
Вы не можете использовать argv [0] для этой цели, обычно он содержит полный путь к исполняемому файлу, но не обязательно - процесс может быть создан с произвольным значением в поле.
Также учтите, что текущий каталог и каталог с исполняемым файлом - это две разные вещи, поэтому getcwd () вам тоже не поможет.
В Windows используйте GetModuleFileName (), в Linux - файлы / dev / proc / procID / ...
initial_path() Boost Filesystem ведет себя как getcwd() POSIX, и ни один из них не делает то, что вы хотите, но добавление argv[0] к любому из них должно сделать это.
Вы можете заметить, что результат не всегда хорош - вы можете получить такие вещи, как /foo/bar/../../baz/a.out или /foo/bar//baz/a.out, но я считаю, что это всегда приводит к правильному пути, который называет исполняемый файл (обратите внимание, что последовательные косые черты в пути свернуты до одного).
Ранее я писал решение, используя envp (третий аргумент main(), который работал в Linux, но не казался работоспособным в Windows, поэтому я по существу рекомендую то же решение, что и кто-то ранее, но с дополнительным объяснением, почему это так. на самом деле правильно, даже если результаты не очень хороши.
Если вы выбираете текущий каталог при первом запуске вашей программы, то вы фактически получаете каталог, из которого была запущена ваша программа. Сохраните значение в переменной и обратитесь к нему позже в своей программе. Это отличается от каталог, в котором находится текущий исполняемый файл программы. Это не обязательно тот же каталог; если кто-то запускает программу из командной строки, то программа является бежать от текущим рабочим каталогом командной строки, даже если файл программы находится в другом месте.
getcwd - это функция POSIX, которая "из коробки" поддерживается всеми POSIX-совместимыми платформами. Вам не нужно делать ничего особенного (кроме включения правильных заголовков unistd.h в Unix и direct.h в Windows).
Поскольку вы создаете программу на языке C, она будет связана с библиотекой времени выполнения c по умолчанию, с которой связаны ВСЕ процессы в системе (исключение специально созданных исключений), и она будет включать эту функцию по умолчанию. CRT никогда не считается внешней библиотекой, поскольку она обеспечивает базовый стандартный интерфейс для ОС.
В Windows функция getcwd устарела в пользу _getcwd. Я думаю, вы могли бы использовать это таким образом.
#include <stdio.h> /* defines FILENAME_MAX */
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
{
return errno;
}
cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */
printf ("The current working directory is %s", cCurrentPath);
Хороший ответ, но я подумал, что «текущий рабочий каталог» - это не то, что нужно.
вы должны добавить, что даже если в некоторых документах говорится, что cCurrentpath может быть нулевым и будет выделен getcwd, getcwd, похоже, не выделяет что-то в Mac OS и незаметно завершает работу вашей программы
почему это было отмечено как правильный ответ, когда исходный постер признал, что это не то, что они хотели ?!
Произошла небольшая ошибка, но, к сожалению, я пока не могу ее редактировать .. строка 10: cCurrentpath: должно быть cCurrentPath
IMO в Windows следует избегать функций с именем POSIXy (некоторые из которых начинаются с подчеркивания). Это не настоящие Windows API, а скорее CRT. API Windows, который вы хотите использовать, - это GetCurrentDirectory (). msdn.microsoft.com/en-us/library/aa364934(VS.85).aspx
Мне нужно было добавить #include <errno.h> и использовать char вместо TCHAR, чтобы это работало.
Зачем делить на sizeof (TCHAR)? Разве вы не хотите разделить на sizeof (char)? Кроме того, не всегда ли размер char должен быть равен 1? Если так, то деление показалось бы излишним.
@allyourcode TCHAR принимает значение char или wchar_t в зависимости от того, используете ли вы Ascii или Unicode. sizeof (wchar_t) равен 2 в Windows.
Просто чтобы уточнить: «текущий каталог» - это каталог, в котором находится файл изображения программы (файл ~ .exe), а «текущий каталог работающий» - это каталог, который автоматически заполняется, если программа использует относительные пути?
Ответ Майка правильный. «Текущий каталог» не всегда совпадает с каталогом, из которого запущен двоичный файл. Например, если приложение работает как служба в Windows, текущий каталог, вероятно, будет C: \ Windows \ System32, тогда как двоичный каталог будет другим.
@LuckyLuke: Или когда приложение запускается с помощью ярлыка (.lnk), который позволяет вам указать текущий рабочий каталог. Так что запрос CWD перед тем, как делать что-либо еще в вашем процессе, тоже бесполезен. Этот ответ просто не отвечает на вопрос.
Он должен быть _WIN32 вместо WINDOWS, WINDOWS больше похож на компилятор.
Возможно, это не то, о чем просил человек, но это ответ, который я искал в Google и хотел ^ _ ^ (нужно было отладить код, и это отлично работает для меня) Спасибо!
Вот код для получения полного пути к исполняющему приложению:
Окна:
char pBuf[256];
size_t len = sizeof(pBuf);
int bytes = GetModuleFileName(NULL, pBuf, len);
return bytes ? bytes : -1;
Linux:
int bytes = MIN(readlink("/proc/self/exe", pBuf, len), len - 1);
if (bytes >= 0)
pBuf[bytes] = '\0';
return bytes;
Я думаю, что это единственный ответ на этот вопрос, причем как для Windows, так и для Linux. Хорошая работа.
Boo для / proc / pid / exe - по какой-то причине не поддерживается в OS X.
Когда я вижу код, который смотрит на /proc, часть меня немного умирает. Весь мир - это не Linux, и даже на этой одной платформе /proc следует рассматривать как подлежащую изменению от версии к версии, от архива к архитектуре и т. д.
Кстати, более переносимый способ получить путь к вашему двоичному файлу в Unix - это посмотреть на argv[0], хотя это может быть подделано процессом, который вас запустил.
@asveikau argv[0] показывает команду, используемую для запуска процесса, поэтому будет отображаться только весь путь, если пользователь ввел весь путь. Если двоичный файл находится в их PATH, они могут просто ввести foo для его запуска или ./foo, если они находятся в текущем каталоге - argv[0] будет недостаточно в любом случае
@Michael Mrozek - это случаи, которые легко обнаружить. Представьте себе логику, которая работает: если argv[0] начинается с '/', рассматривать как абсолютный путь, в противном случае проверьте, содержит ли он '/', если это так, это относительный путь, и вам нужно вставить текущий рабочий каталог, в противном случае вам нужно найти свой двоичный файл в $PATH . Как я уже сказал, это не идеально - я могу называть execve() с argv[0] как "omg ponies", и execve() все равно будет работать.
если они запускаются с использованием команды с псевдонимом в Linux, является ли argv [0] «именем команды» или расширено?
Решение Windows неправильно проверяет возвращаемое значение (или ожидает, что вызывающий абонент выполнит дополнительную проверку ошибок). Кроме того, он возвращает полный путь к исполняемому файлу. Если вам нужен только каталог (как задается вопросом), вам нужно удалить имя файла с конца пути.
Как насчет добавления char pBuf[256]; size_t len = sizeof(pBuf);, чтобы решение было более четким.
«Спасибо, Майк, ты герой!» теперь гордо присутствует где-то в проекте, над которым я сейчас работаю. Еще я хотел выразить благодарность «лично», так что: спасибо, Майк, ты герой! Ага, сейчас 3:30 утра.
Вы должны использовать "/proc/self/exe" вместо этой строковой копии mojo. Кроме того, отличный ответ!
Просто чтобы с опозданием навалить сюда ...
стандартного решения не существует, потому что языки не зависят от базовых файловых систем, поэтому, как говорили другие, концепция файловой системы на основе каталогов выходит за рамки языков c / C++.
кроме того, вам нужен не текущий рабочий каталог, а каталог, в котором работает программа, который должен учитывать, как программа попала туда, где она находится, то есть была ли она порождена как новый процесс через вилку и т. д. Чтобы получить каталог, в котором выполняется программа, как показали решения, необходимо, чтобы вы получили эту информацию из структур управления процессами рассматриваемой операционной системы, которая является единственным авторитетом по этому вопросу. Таким образом, по определению, это решение для конкретной ОС.
Как упоминалось в Минок, такая функциональность не указана в стандарте C или стандарте C++. Это считается чисто специфической функцией ОС и определено, например, в стандарте POSIX.
Thorsten79 дал хорошее предложение, это библиотека Boost.Filesystem. Однако это может быть неудобно, если вы не хотите иметь какие-либо зависимости времени компоновки в двоичной форме для вашей программы.
Хорошей альтернативой, которую я бы порекомендовал, является сбор 100% только заголовков Библиотеки STLSoft C++Мэтью Уилсон (автор обязательных к прочтению книг о C++). Есть переносимый фасад. PlatformSTL предоставляет доступ к системному API: WinSTL для Windows и UnixSTL в Unix, так что это переносимое решение. Все системные элементы указываются с использованием трейтов и политик, поэтому это расширяемая структура. Конечно, есть библиотека файловой системы.
В Windows самый простой способ - использовать функцию _get_pgmptr в stdlib.h, чтобы получить указатель на строку, которая представляет собой абсолютный путь к исполняемому файлу, включая имя исполняемого файла.
char* path;
_get_pgmptr(&path);
printf(path); // Example output: C:/Projects/Hello/World.exe
Для системы Windows в консоли вы можете использовать команду system (dir). Консоль дает вам информацию о каталоге и т. д. Прочтите о команде dir в cmd. Но для Unix-подобных систем я не знаю ... Если эта команда запущена, прочтите команду bash. ls не отображает каталог ...
Пример:
int main()
{
system("dir");
system("pause"); //this wait for Enter-key-press;
return 0;
}
Это из cplusplus форум
В окнах:
#include <string>
#include <windows.h>
std::string getexepath()
{
char result[ MAX_PATH ];
return std::string( result, GetModuleFileName( NULL, result, MAX_PATH ) );
}
В Linux:
#include <string>
#include <limits.h>
#include <unistd.h>
std::string getexepath()
{
char result[ PATH_MAX ];
ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
return std::string( result, (count > 0) ? count : 0 );
}
В HP-UX:
#include <string>
#include <limits.h>
#define _PSTAT64
#include <sys/pstat.h>
#include <sys/types.h>
#include <unistd.h>
std::string getexepath()
{
char result[ PATH_MAX ];
struct pst_status ps;
if (pstat_getproc( &ps, sizeof( ps ), 0, getpid() ) < 0)
return std::string();
if (pstat_getpathname( result, PATH_MAX, &ps.pst_fid_text ) < 0)
return std::string();
return std::string( result );
}
Это решение Windows не будет обрабатывать в пути символы, отличные от ANSI. Вероятно, вам следует использовать GetModuleFileNameW и явно преобразовать его в UTF-8 (будьте осторожны, чтобы преобразовать его обратно, когда вам нужно выполнить команду файловой системы).
Для решения Windows я получаю ошибку error: cannot convert 'char*' to 'LPWCH {aka wchar_t*}' for argument '2' to 'DWORD GetModuleFileNameW(HMODULE, LPWCH, DWORD)' при компиляции с MinGW.
@Adrian, я обычно не программист Windows, но разве нет DEFINE или как-то еще, чтобы указать вашему компилятору автоматически использовать вид функций _W ()?
@Octopus: чтобы использовать широкие вызовы, вам нужно будет использовать WCHAR (вместо char) и std :: wstring (вместо std :: string).
#include <windows.h>
using namespace std;
// The directory path returned by native GetCurrentDirectory() no end backslash
string getCurrentDirectoryOnWindows()
{
const unsigned long maxDir = 260;
char currentDir[maxDir];
GetCurrentDirectory(maxDir, currentDir);
return string(currentDir);
}
Вот что я сделал для относительных путей. Я знаю возраст этого вопроса, я просто хочу предложить более простой ответ, который работает в большинстве случаев:
Скажем, у вас есть такой путь:
"path/to/file/folder"
По какой-то причине исполняемые файлы Linux, созданные в eclipse, отлично с этим работают. Однако окна очень запутываются, если им задан такой путь для работы!
Как указывалось выше, есть несколько способов получить текущий путь к исполняемому файлу, но самый простой способ, который, как я считаю, работает очаровательно в большинстве случаев, - это добавить это к ПЕРЕДНЕМУ вашего пути:
"./path/to/file/folder"
Простое добавление "./" должно помочь вам разобраться! :) Затем вы можете начать загрузку из любого каталога, который хотите, при условии, что он находится с самим исполняемым файлом.
Обновлено: Это не сработает, если вы попытаетесь запустить исполняемый файл из code :: blocks, если используется среда разработки, поскольку по какой-то причине code :: blocks не загружает материал правильно ...: D
EDIT2: Я обнаружил некоторые новые вещи: если вы укажете статический путь, подобный этому, в своем коде (при условии, что вам нужно загрузить Example.data):
"resources/Example.data"
Если вы затем запустите свое приложение из фактического каталога (или в Windows вы создадите ярлык и установите рабочий каталог в каталог вашего приложения), тогда оно будет работать так. Помните об этом при отладке проблем, связанных с отсутствующими путями к ресурсам / файлам. (Особенно в IDE, которые устанавливают неправильный рабочий каталог при запуске сборки exe из IDE)
Я знаю, что уже очень поздно давать ответ на этот вопрос, но я обнаружил, что ни один из ответов не был для меня так полезен, как мое собственное решение. Очень простой способ получить путь от вашего CWD к вашей папке bin выглядит следующим образом:
int main(int argc, char* argv[])
{
std::string argv_str(argv[0]);
std::string base = argv_str.substr(0, argv_str.find_last_of("/"));
}
Теперь вы можете просто использовать это как основу для своего относительного пути. Так, например, у меня есть такая структура каталогов:
main
----> test
----> src
----> bin
и я хочу скомпилировать исходный код в bin и написать журнал для тестирования. Я могу просто добавить эту строку в свой код.
std::string pathToWrite = base + "/../test/test.log";
Я пробовал этот подход в Linux, используя полный путь, псевдоним и т. д., И он отлично работает.
ПРИМЕЧАНИЕ:
Если вы работаете в Windows, в качестве разделителя файлов следует использовать символ '\', а не '/'. Вам также придется избежать этого, например:
std::string base = argv[0].substr(0, argv[0].find_last_of("\"));
Я думаю, что это должно сработать, но не тестировал, поэтому будут признательны за комментарии, если это сработает, или исправление, если нет.
Да, это работает и в Windows. Я считаю, что это лучшее решение. Насколько мне известно, argv [0] всегда сохраняет путь к исполняемому файлу.
argv[0] - очень хорошая идея, но, к сожалению, в Linux я получаю «./my_executable_name» или «./make/my_executable_name». В основном то, что я получаю, полностью зависит от того, как я его запускаю
@Xeverous: ну и что? Если у меня есть какие-то файлы, относящиеся к моему исполняемому файлу, которые ему нужно открыть, начиная с «./» или «./make/» в ваших случаях должно работать. "." - это текущий рабочий каталог, а argv [0] сообщит вам относительный путь к исполняемому файлу оттуда, что именно то, что нужно OP. В любом случае это именно то, что мне нужно.
Файловая система TS теперь стандарт (и поддерживается gcc 5.3+ и clang 3.9+), поэтому вы можете использовать из нее функцию current_path():
std::string path = std::experimental::filesystem::current_path();
В gcc (5.3+) для включения файловой системы вам необходимо использовать:
#include <experimental/filesystem>
и свяжите свой код с флагом -lstdc++fs.
Если вы хотите использовать файловую систему с Microsoft Visual Studio, тогда прочитай это.
Из указанной ссылки 1-2) Returns the absolute path of the current working directory, obtained as if by POSIX getcwd. (2) returns path() if error occurs. Downvoted, поскольку OP конкретно спрашивает о текущем пути исполняемого файла, а не о текущем рабочем каталоге.
Команда linux bash какое имя программы сообщит путь к программе.
Даже если можно было бы выполнить команду which из вашей программы и направить вывод в файл tmp и программу впоследствии читает этот файл tmp, он не скажет вам, выполняется ли эта программа. Он только сообщает вам, где находится программа с таким именем.
Что требуется, так это получить номер идентификатора вашего процесса и разобрать путь к имени
В моей программе я хочу знать, была ли программа выполняется из каталога bin пользователя или из другого каталога по пути или из / usr / bin. / usr / bin будет содержать поддерживаемую версию. Мне кажется, что в Linux есть одно портативное решение.
Библиотечное решение (хотя я знаю, что об этом не просили).
Если вы используете Qt:
QCoreApplication::applicationDirPath()
Используйте realpath() в stdlib.h следующим образом:
char *working_dir_path = realpath(".", NULL);
Работает с C++ 11, начиная с экспериментальной файловой системы, и с C++ 14-C++ 17, а также с официальной файловой системой.
application.h:
#pragma once
//
// https://en.cppreference.com/w/User:D41D8CD98F/feature_testing_macros
//
#ifdef __cpp_lib_filesystem
#include <filesystem>
#else
#include <experimental/filesystem>
namespace std {
namespace filesystem = experimental::filesystem;
}
#endif
std::filesystem::path getexepath();
application.cpp:
#include "application.h"
#ifdef _WIN32
#include <windows.h> //GetModuleFileNameW
#else
#include <limits.h>
#include <unistd.h> //readlink
#endif
std::filesystem::path getexepath()
{
#ifdef _WIN32
wchar_t path[MAX_PATH] = { 0 };
GetModuleFileNameW(NULL, path, MAX_PATH);
return path;
#else
char result[PATH_MAX];
ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
return std::string(result, (count > 0) ? count : 0);
#endif
}
Хороший ответ, но добавление деклараций или определений в пространство имен std является неопределенным поведением.. Чтобы избежать этого, вы можете добавить оба пространства имен std::filesystem и std::experimental::filesystem в третье пространство имен по вашему выбору или просто использовать using std::filesystem::path, если вы не возражаете добавить объявление path в глобальное пространство имен.
Думаю, после C++ 14 экспериментальная :: файловая система больше не используется, так что можно просто забыть об этом? (переходит в первую ветку #if)
Всего два цента, но разве следующий код не работает на C++ 17?
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main(int argc, char* argv[])
{
std::cout << "Path is " << fs::path(argv[0]).parent_path() << '\n';
}
Кажется, у меня работает по крайней мере на Linux.
Основываясь на предыдущей идее, теперь у меня есть:
std::filesystem::path prepend_exe_path(const std::string& filename, const std::string& exe_path = "");
При реализации:
fs::path prepend_exe_path(const std::string& filename, const std::string& exe_path)
{
static auto exe_parent_path = fs::path(exe_path).parent_path();
return exe_parent_path / filename;
}
И трюк с инициализацией в main():
(void) prepend_exe_path("", argv[0]);
Спасибо @Sam Redway за идею argv [0]. И, конечно же, я понимаю, что C++ 17 не было много лет, когда ОП задал вопрос.
Путь к текущему .exe
#include <Windows.h>
std::wstring getexepathW()
{
wchar_t result[MAX_PATH];
return std::wstring(result, GetModuleFileNameW(NULL, result, MAX_PATH));
}
std::wcout << getexepathW() << std::endl;
// -------- OR --------
std::string getexepathA()
{
char result[MAX_PATH];
return std::string(result, GetModuleFileNameA(NULL, result, MAX_PATH));
}
std::cout << getexepathA() << std::endl;
Это дублирует другой предыдущий ответ и, в отличие от этого, завершится ошибкой в сборках ANSI, потому что неквалифицированный GetModuleFileName преобразуется в GetModuleFileNameA вместо GetModuleFileNameW.
Я изменил ответ, включив оба варианта. Много любви
Если вы не сможете надежно извлечь путь из
argv[0], метод будет сильно зависеть от ОС.