From 43901544cb359a1aa30cd7be034d435e12266d56 Mon Sep 17 00:00:00 2001 From: AlrondPrime Date: Mon, 28 Apr 2025 20:46:44 +0300 Subject: [PATCH] Resolve Issue #483 Add support of std::initializer_list for windows::default_launcher::operator() --- .../process/v2/windows/default_launcher.hpp | 190 +++++++++++++----- 1 file changed, 136 insertions(+), 54 deletions(-) diff --git a/include/boost/process/v2/windows/default_launcher.hpp b/include/boost/process/v2/windows/default_launcher.hpp index d0ca19b4d..df4886c61 100644 --- a/include/boost/process/v2/windows/default_launcher.hpp +++ b/include/boost/process/v2/windows/default_launcher.hpp @@ -235,6 +235,7 @@ struct default_launcher default_launcher() = default; + /// with ExecutionContext template auto operator()(ExecutionContext & context, const typename std::enable_if enable_init { error_code ec; - auto proc = (*this)(context, ec, executable, std::forward(args), std::forward(inits)...); + auto proc = create_process(context.get_executor(), ec, executable, std::forward(args), std::forward(inits)...); if (ec) v2::detail::throw_error(ec, "default_launcher"); @@ -252,7 +253,25 @@ struct default_launcher return proc; } + /// with ExecutionContext and initializer_list + template + auto operator()(ExecutionContext& context, + const typename std::enable_if::value, + filesystem::path >::type& executable, + std::initializer_list args, + Inits && ... inits) -> enable_init + { + error_code ec; + auto proc = create_process(context.get_executor(), ec, executable, args, std::forward(inits)...); + + if (ec) + v2::detail::throw_error(ec, "default_launcher"); + + return proc; + } + /// with ExecutionContext and error_code template auto operator()(ExecutionContext & context, error_code & ec, @@ -262,9 +281,23 @@ struct default_launcher Args && args, Inits && ... inits ) -> enable_init { - return (*this)(context.get_executor(), ec, executable, std::forward(args), std::forward(inits)...); + return create_process(context.get_executor(), ec, executable, std::forward(args), std::forward(inits)...); } + /// with ExecutionContext, error_code and initializer_list + template + auto operator()(ExecutionContext& context, + error_code& ec, + const typename std::enable_if::value, + filesystem::path >::type& executable, + std::initializer_list args, + Inits && ... inits) -> enable_init + { + return create_process(context.get_executor(), ec, executable, args, std::forward(inits)...); + } + + /// with Executor template auto operator()(Executor exec, const typename std::enable_if< @@ -275,7 +308,26 @@ struct default_launcher Inits && ... inits ) -> enable_init { error_code ec; - auto proc = (*this)(std::move(exec), ec, executable, std::forward(args), std::forward(inits)...); + auto proc = create_process(std::move(exec), ec, executable, std::forward(args), std::forward(inits)...); + + if (ec) + detail::throw_error(ec, "default_launcher"); + + return proc; + } + + /// with Executor and initializer_list + template + auto operator()(Executor exec, + const typename std::enable_if< + net::execution::is_executor::value + || net::is_executor::value, + filesystem::path >::type& executable, + std::initializer_list args, + Inits && ... inits) -> enable_init + { + error_code ec; + auto proc = create_process(std::move(exec), ec, executable, args, std::forward(inits)...); if (ec) detail::throw_error(ec, "default_launcher"); @@ -283,6 +335,7 @@ struct default_launcher return proc; } + /// with Executor and error_code template auto operator()(Executor exec, error_code & ec, @@ -293,58 +346,21 @@ struct default_launcher Args && args, Inits && ... inits ) -> enable_init { - auto command_line = this->build_command_line(executable, std::forward(args)); - - ec = detail::on_setup(*this, executable, command_line, inits...); - - if (ec) - { - detail::on_error(*this, executable, command_line, ec, inits...); - return basic_process(exec); - } - - if (!inherited_handles.empty()) - { - set_handle_list(ec); - if (ec) - return basic_process(exec); - } - - auto ok = ::CreateProcessW( - executable.empty() ? nullptr : executable.c_str(), - command_line.empty() ? nullptr : &command_line.front(), - process_attributes, - thread_attributes, - inherited_handles.empty() ? FALSE : TRUE, - creation_flags, - environment, - current_directory.empty() ? nullptr : current_directory.c_str(), - &startup_info.StartupInfo, - &process_information); - - if (ok == 0) - { - BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec); - detail::on_error(*this, executable, command_line, ec, inits...); - - if (process_information.hProcess != INVALID_HANDLE_VALUE) - ::CloseHandle(process_information.hProcess); - if (process_information.hThread != INVALID_HANDLE_VALUE) - ::CloseHandle(process_information.hThread); - - return basic_process(exec); - } - else - { - detail::on_success(*this, executable, command_line, inits...); - - if (process_information.hThread != INVALID_HANDLE_VALUE) - ::CloseHandle(process_information.hThread); + return create_process(std::move(exec), ec, executable, std::forward(args), std::forward(inits)...); + } - return basic_process(exec, - this->process_information.dwProcessId, - this->process_information.hProcess); - } + /// with Executor, error_code and initializer_list + template + auto operator()(Executor exec, + error_code& ec, + const typename std::enable_if< + net::execution::is_executor::value || + net::is_executor::value, + filesystem::path >::type& executable, + std::initializer_list args, + Inits && ... inits) -> enable_init + { + return create_process(std::move(exec), ec, executable, args, std::forward(inits)...); } BOOST_PROCESS_V2_DECL static @@ -425,6 +441,72 @@ struct default_launcher BOOST_PROCESS_V2_DECL LPPROC_THREAD_ATTRIBUTE_LIST get_thread_attribute_list(error_code & ec); BOOST_PROCESS_V2_DECL void set_handle_list(error_code & ec); + +private: + // actual process creation implementation + template + auto create_process(Executor exec, + error_code& ec, + const typename std::enable_if< + net::execution::is_executor::value || + net::is_executor::value, + filesystem::path >::type& executable, + Args&& args, + Inits && ... inits) + { + auto command_line = this->build_command_line(executable, std::forward(args)); + + ec = detail::on_setup(*this, executable, command_line, inits...); + + if (ec) + { + detail::on_error(*this, executable, command_line, ec, inits...); + return basic_process(exec); + } + + if (!inherited_handles.empty()) + { + set_handle_list(ec); + if (ec) + return basic_process(exec); + } + + auto ok = ::CreateProcessW( + executable.empty() ? nullptr : executable.c_str(), + command_line.empty() ? nullptr : &command_line.front(), + process_attributes, + thread_attributes, + inherited_handles.empty() ? FALSE : TRUE, + creation_flags, + environment, + current_directory.empty() ? nullptr : current_directory.c_str(), + &startup_info.StartupInfo, + &process_information); + + if (ok == 0) + { + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec); + detail::on_error(*this, executable, command_line, ec, inits...); + + if (process_information.hProcess != INVALID_HANDLE_VALUE) + ::CloseHandle(process_information.hProcess); + if (process_information.hThread != INVALID_HANDLE_VALUE) + ::CloseHandle(process_information.hThread); + + return basic_process(exec); + } + else + { + detail::on_success(*this, executable, command_line, inits...); + + if (process_information.hThread != INVALID_HANDLE_VALUE) + ::CloseHandle(process_information.hThread); + + return basic_process(exec, + this->process_information.dwProcessId, + this->process_information.hProcess); + } + } };