LINUX.ORG.RU

История изменений

Исправление rumgot, (текущая версия) :

Я смотрел, как реализовано в Qt и делал похоже, немного более упрощенно.

Linux: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp.html#2349

Windows: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication_win.cpp.html#_Z12qAppFileNamev

Я у себя делал так:

#if defined HOST_SYSTEM_LINUX

#include <unistd.h>
#include <filesystem>

static std::filesystem::path applicationFilePathLinux() {
    using namespace std::filesystem;
    using namespace std;
    return canonical(path("/proc") / path(to_string(getpid())) / path("exe"));
}

static std::filesystem::path applicationFileDirectoryLinux() { return applicationFilePathLinux().parent_path(); }

std::filesystem::path applicationFilePath() { return applicationFilePathLinux(); }
std::filesystem::path applicationDirectoryPath() { return applicationFileDirectoryLinux(); }

#elif defined HOST_SYSTEM_WINDOWS

#include <algorithm>
#include <filesystem>
#include <string>
#include <vector>

#include <windows.h>

static std::filesystem::path applicationFilePathWindows() {

    std::vector<wchar_t> readBuffer(MAX_PATH + 1);
    unsigned long readedCount;
    readedCount = GetModuleFileName(nullptr, readBuffer.data(), readBuffer.size());

    if (readBuffer.size() < readedCount) {
        throw std::runtime_error("applicationFilePathWindows() Error name exceeds buffer size.");
    }

    std::wstring executablePath;
    std::copy(readBuffer.begin(), readBuffer.end(), std::back_inserter(executablePath));
    return std::filesystem::path(executablePath);
}
static std::filesystem::path applicationDirectoryPathWindows() { return applicationFilePathWindows().parent_path(); }
std::filesystem::path applicationFilePath() { return applicationFilePathWindows(); }
std::filesystem::path applicationDirectoryPath() { return applicationDirectoryPathWindows(); }

#endif

Для Windows нужно определить символы препроцессора _UNICODE и UNICODE. Также в зависимости от системы нужно определить символы препроцессора HOST_SYSTEM_LINUX или HOST_SYSTEM_WINDOWS (я это делаю через CMake).

Исправление rumgot, :

Я смотрел, как реализовано в Qt и делал похоже, немного более упрощенно.

Linux: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp.html#2349

Windows: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication_win.cpp.html#_Z12qAppFileNamev

Я у себя делал так:

#if defined HOST_SYSTEM_LINUX

#include <unistd.h>
#include <filesystem>

static std::filesystem::path applicationFilePathLinux() {
    using namespace std::filesystem;
    using namespace std;
    return canonical(path("/proc") / path(to_string(getpid())) / path("exe"));
}

static std::filesystem::path applicationFileDirectoryLinux() { return applicationFilePathLinux().parent_path(); }

std::filesystem::path applicationFilePath() { return applicationFilePathLinux(); }
std::filesystem::path applicationDirectoryPath() { return applicationFileDirectoryLinux(); }

#elif defined HOST_SYSTEM_WINDOWS

#include <algorithm>
#include <filesystem>
#include <string>
#include <vector>

#include <windows.h>

static std::filesystem::path applicationFilePathWindows() {

    std::vector<wchar_t> readBuffer(MAX_PATH + 1);
    unsigned long readedCount;
    readedCount = GetModuleFileName(nullptr, readBuffer.data(), readBuffer.size());

    if (readBuffer.size() < readedCount) {
        throw std::runtime_error("applicationFilePathWindows() Error name exceeds buffer size.");
    }

    std::wstring executablePath;
    std::copy(readBuffer.begin(), readBuffer.end(), std::back_inserter(executablePath));
    return std::filesystem::path(executablePath);
}
static std::filesystem::path applicationDirectoryPathWindows() { return applicationFilePathWindows().parent_path(); }
std::filesystem::path applicationFilePath() { return applicationFilePathWindows(); }
std::filesystem::path applicationDirectoryPath() { return applicationDirectoryPathWindows(); }

#endif

Исправление rumgot, :

Я смотрел, как реализовано в Qt и делал похоже, немного более упрощенно.

Linux: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp.html#2349

Windows: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication_win.cpp.html#_Z12qAppFileNamev

Я у себя делал так:

#include "applicationfilepath.h"

#if defined HOST_SYSTEM_LINUX

#include <unistd.h>
#include <filesystem>

static std::filesystem::path applicationFilePathLinux() {
    using namespace std::filesystem;
    using namespace std;
    return canonical(path("/proc") / path(to_string(getpid())) / path("exe"));
}

static std::filesystem::path applicationFileDirectoryLinux() { return applicationFilePathLinux().parent_path(); }

std::filesystem::path cetc::applicationFilePath() { return applicationFilePathLinux(); }
std::filesystem::path cetc::applicationDirectoryPath() { return applicationFileDirectoryLinux(); }

#elif defined HOST_SYSTEM_WINDOWS

#include <algorithm>
#include <filesystem>
#include <string>
#include <vector>

#include <windows.h>

static std::filesystem::path applicationFilePathWindows() {

    std::vector<wchar_t> readBuffer(MAX_PATH + 1);
    unsigned long readedCount;
    readedCount = GetModuleFileName(nullptr, readBuffer.data(), readBuffer.size());

    if (readBuffer.size() < readedCount) {
        throw std::runtime_error("applicationFilePathWindows() Error name exceeds buffer size.");
    }

    std::wstring executablePath;
    std::copy(readBuffer.begin(), readBuffer.end(), std::back_inserter(executablePath));
    return std::filesystem::path(executablePath);
}
static std::filesystem::path applicationDirectoryPathWindows() { return applicationFilePathWindows().parent_path(); }
std::filesystem::path cetc::applicationFilePath() { return applicationFilePathWindows(); }
std::filesystem::path cetc::applicationDirectoryPath() { return applicationDirectoryPathWindows(); }

#endif

Исходная версия rumgot, :

Я смотрел, как реализовано в Qt и делал похоже.

Linux: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp.html#2349

Windows: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication_win.cpp.html#_Z12qAppFileNamev

Я у себя делал так:

#include "applicationfilepath.h"

#if defined HOST_SYSTEM_LINUX

#include <unistd.h>
#include <filesystem>

static std::filesystem::path applicationFilePathLinux() {
    using namespace std::filesystem;
    using namespace std;
    return canonical(path("/proc") / path(to_string(getpid())) / path("exe"));
}

static std::filesystem::path applicationFileDirectoryLinux() { return applicationFilePathLinux().parent_path(); }

std::filesystem::path cetc::applicationFilePath() { return applicationFilePathLinux(); }
std::filesystem::path cetc::applicationDirectoryPath() { return applicationFileDirectoryLinux(); }

#elif defined HOST_SYSTEM_WINDOWS

#include <algorithm>
#include <filesystem>
#include <string>
#include <vector>

#include <windows.h>

static std::filesystem::path applicationFilePathWindows() {

    std::vector<wchar_t> readBuffer(MAX_PATH + 1);
    unsigned long readedCount;
    readedCount = GetModuleFileName(nullptr, readBuffer.data(), readBuffer.size());

    if (readBuffer.size() < readedCount) {
        throw std::runtime_error("applicationFilePathWindows() Error name exceeds buffer size.");
    }

    std::wstring executablePath;
    std::copy(readBuffer.begin(), readBuffer.end(), std::back_inserter(executablePath));
    return std::filesystem::path(executablePath);
}
static std::filesystem::path applicationDirectoryPathWindows() { return applicationFilePathWindows().parent_path(); }
std::filesystem::path cetc::applicationFilePath() { return applicationFilePathWindows(); }
std::filesystem::path cetc::applicationDirectoryPath() { return applicationDirectoryPathWindows(); }

#endif