From 01e95de886413c252ee1a419ed0a7c41435847e6 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Sun, 18 Oct 2020 03:20:06 +0300 Subject: Process: add get_exe_path() --- 3rdparty/winapi/utf8 | 2 +- include/winapi/process.hpp | 2 ++ src/path.cpp | 5 ++++- src/process.cpp | 26 ++++++++++++++++++++++++++ test/unit_tests/process.cpp | 5 +++++ 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/3rdparty/winapi/utf8 b/3rdparty/winapi/utf8 index 8fae97c..25f39c1 160000 --- a/3rdparty/winapi/utf8 +++ b/3rdparty/winapi/utf8 @@ -1 +1 @@ -Subproject commit 8fae97c1400493c23853496d0f59a3047bdd3da6 +Subproject commit 25f39c16c2024bd7c9e03b4bc84625d0c8eed849 diff --git a/include/winapi/process.hpp b/include/winapi/process.hpp index 469653c..5f841a0 100644 --- a/include/winapi/process.hpp +++ b/include/winapi/process.hpp @@ -56,6 +56,8 @@ public: int get_exit_code() const; + static std::string get_exe_path(); + static Resource get_resource(unsigned int id); static std::string get_resource_string(unsigned int id); diff --git a/src/path.cpp b/src/path.cpp index 2c2deda..3df5918 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -16,8 +16,11 @@ namespace winapi { namespace { std::wstring do_canonicalize(const std::wstring& path) { + BOOST_STATIC_CONSTEXPR std::size_t init_buffer_size = MAX_PATH; + static_assert(init_buffer_size > 0, "init_buffer_size must be positive"); + std::vector buffer; - buffer.resize(MAX_PATH); + buffer.resize(init_buffer_size); while (true) { const auto nch = ::GetFullPathNameW(path.c_str(), buffer.size(), buffer.data(), NULL); diff --git a/src/process.cpp b/src/process.cpp index d3ce3a4..7e3a9e7 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -122,6 +122,32 @@ HMODULE Process::get_exe_module() { return module; } +std::string Process::get_exe_path() { + BOOST_STATIC_CONSTEXPR std::size_t init_buffer_size = MAX_PATH; + static_assert(init_buffer_size > 0, "init_buffer_size must be positive"); + + std::vector buffer; + buffer.resize(init_buffer_size); + + while (true) { + SetLastError(ERROR_SUCCESS); + + const auto nch = ::GetModuleFileNameW(NULL, buffer.data(), buffer.size()); + + if (nch == 0) { + throw error::windows(GetLastError(), "GetModuleFileNameW"); + } + + if (nch == buffer.size() && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + buffer.resize(2 * buffer.size()); + continue; + } + + buffer.resize(nch); + return narrow(buffer); + } +} + std::string Process::get_resource_string(unsigned int id) { wchar_t* s = nullptr; diff --git a/test/unit_tests/process.cpp b/test/unit_tests/process.cpp index 1c87b27..0a6cb27 100644 --- a/test/unit_tests/process.cpp +++ b/test/unit_tests/process.cpp @@ -21,6 +21,11 @@ using namespace winapi::process; BOOST_AUTO_TEST_SUITE(process_tests) +BOOST_AUTO_TEST_CASE(get_exe_path) { + const auto path = Process::get_exe_path(); + BOOST_TEST_MESSAGE("Executable path: " << path); +} + BOOST_FIXTURE_TEST_CASE(echo, WithEchoExe) { const CommandLine cmd_line{get_echo_exe(), {"1", "2", "3"}}; const auto process = Process::create(cmd_line); -- cgit v1.2.3