diff --git a/src/platform/common.h b/src/platform/common.h index 5914017f..d626f9b3 100644 --- a/src/platform/common.h +++ b/src/platform/common.h @@ -384,7 +384,7 @@ namespace platf { display_names(mem_type_e hwdevice_type); boost::process::child - run_command(bool elevated, const std::string &cmd, boost::filesystem::path &working_dir, boost::process::environment &env, FILE *file, std::error_code &ec, boost::process::group *group); + run_command(bool elevated, bool interactive, const std::string &cmd, boost::filesystem::path &working_dir, boost::process::environment &env, FILE *file, std::error_code &ec, boost::process::group *group); enum class thread_priority_e : int { low, diff --git a/src/platform/linux/misc.cpp b/src/platform/linux/misc.cpp index 118912d1..87f22ca3 100644 --- a/src/platform/linux/misc.cpp +++ b/src/platform/linux/misc.cpp @@ -159,7 +159,7 @@ namespace platf { } bp::child - run_command(bool elevated, const std::string &cmd, boost::filesystem::path &working_dir, bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) { + run_command(bool elevated, bool interactive, const std::string &cmd, boost::filesystem::path &working_dir, bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) { if (!group) { if (!file) { return bp::child(cmd, env, bp::start_dir(working_dir), bp::std_out > bp::null, bp::std_err > bp::null, ec); @@ -190,7 +190,7 @@ namespace platf { boost::process::environment _env = boost::this_process::environment(); std::error_code ec; - auto child = run_command(false, cmd, working_dir, _env, nullptr, ec, nullptr); + auto child = run_command(false, false, cmd, working_dir, _env, nullptr, ec, nullptr); if (ec) { BOOST_LOG(warning) << "Couldn't open url ["sv << url << "]: System: "sv << ec.message(); } diff --git a/src/platform/macos/misc.mm b/src/platform/macos/misc.mm index 46209dda..85ac20d9 100644 --- a/src/platform/macos/misc.mm +++ b/src/platform/macos/misc.mm @@ -159,7 +159,7 @@ namespace platf { } bp::child - run_command(bool elevated, const std::string &cmd, boost::filesystem::path &working_dir, bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) { + run_command(bool elevated, bool interactive, const std::string &cmd, boost::filesystem::path &working_dir, bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) { if (!group) { if (!file) { return bp::child(cmd, env, bp::start_dir(working_dir), bp::std_out > bp::null, bp::std_err > bp::null, ec); @@ -189,7 +189,7 @@ namespace platf { boost::process::environment _env = boost::this_process::environment(); std::error_code ec; - auto child = run_command(false, cmd, working_dir, _env, nullptr, ec, nullptr); + auto child = run_command(false, false, cmd, working_dir, _env, nullptr, ec, nullptr); if (ec) { BOOST_LOG(warning) << "Couldn't open url ["sv << url << "]: System: "sv << ec.message(); } diff --git a/src/platform/windows/misc.cpp b/src/platform/windows/misc.cpp index de851325..2ab811cd 100644 --- a/src/platform/windows/misc.cpp +++ b/src/platform/windows/misc.cpp @@ -567,6 +567,7 @@ namespace platf { * process is returned. Otherwise, an error code is returned. * * @param elevated Specify to elevate the process or not + * @param interactive Specifies whether this will run in a window or hidden * @param cmd The command to run * @param working_dir The working directory for the new process * @param env The environment variables to use for the new process @@ -577,7 +578,7 @@ namespace platf { * @return A `bp::child` object representing the new process, or an empty `bp::child` object if the launch fails */ bp::child - run_command(bool elevated, const std::string &cmd, boost::filesystem::path &working_dir, bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) { + run_command(bool elevated, bool interactive, const std::string &cmd, boost::filesystem::path &working_dir, bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) { BOOL ret; // Convert cmd, env, and working_dir to the appropriate character sets for Win32 APIs std::wstring wcmd = utf8_to_wide_string(cmd); @@ -597,6 +598,11 @@ namespace platf { free_proc_thread_attr_list(list); }); + DWORD creation_flags = EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT | CREATE_BREAKAWAY_FROM_JOB; + + // Create a new console for interactive processes and use no console for non-interactive processes + creation_flags |= interactive ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW; + if (is_running_as_system()) { // Duplicate the current user's token HANDLE user_token = retrieve_users_token(elevated); @@ -625,7 +631,7 @@ namespace platf { NULL, NULL, !!(startup_info.StartupInfo.dwFlags & STARTF_USESTDHANDLES), - EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE | CREATE_BREAKAWAY_FROM_JOB, + creation_flags, env_block.data(), start_dir.empty() ? NULL : start_dir.c_str(), (LPSTARTUPINFOW) &startup_info, @@ -640,7 +646,7 @@ namespace platf { NULL, NULL, !!(startup_info.StartupInfo.dwFlags & STARTF_USESTDHANDLES), - EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE | CREATE_BREAKAWAY_FROM_JOB, + creation_flags, env_block.data(), start_dir.empty() ? NULL : start_dir.c_str(), (LPSTARTUPINFOW) &startup_info, @@ -660,13 +666,12 @@ namespace platf { // set working dir to Windows system directory auto working_dir = boost::filesystem::path(std::getenv("SystemRoot")); - // this isn't ideal as it briefly shows a command window - // but start a command built into cmd, not an executable - std::string cmd = R"(cmd /C "start )" + url + R"(")"; - boost::process::environment _env = boost::this_process::environment(); std::error_code ec; - auto child = run_command(false, cmd, working_dir, _env, nullptr, ec, nullptr); + + // Launch this as a non-interactive non-elevated command to avoid an extra console window + std::string cmd = R"(cmd /C "start )" + url + R"(")"; + auto child = run_command(false, false, cmd, working_dir, _env, nullptr, ec, nullptr); if (ec) { BOOST_LOG(warning) << "Couldn't open url ["sv << url << "]: System: "sv << ec.message(); } diff --git a/src/process.cpp b/src/process.cpp index f8875452..b1efca21 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -136,7 +136,7 @@ namespace proc { find_working_directory(cmd.do_cmd, _env) : boost::filesystem::path(_app.working_dir); BOOST_LOG(info) << "Executing Do Cmd: ["sv << cmd.do_cmd << ']'; - auto child = platf::run_command(cmd.elevated, cmd.do_cmd, working_dir, _env, _pipe.get(), ec, nullptr); + auto child = platf::run_command(cmd.elevated, true, cmd.do_cmd, working_dir, _env, _pipe.get(), ec, nullptr); if (ec) { BOOST_LOG(error) << "Couldn't run ["sv << cmd.do_cmd << "]: System: "sv << ec.message(); @@ -157,7 +157,7 @@ namespace proc { find_working_directory(cmd, _env) : boost::filesystem::path(_app.working_dir); BOOST_LOG(info) << "Spawning ["sv << cmd << "] in ["sv << working_dir << ']'; - auto child = platf::run_command(_app.elevated, cmd, working_dir, _env, _pipe.get(), ec, nullptr); + auto child = platf::run_command(_app.elevated, true, cmd, working_dir, _env, _pipe.get(), ec, nullptr); if (ec) { BOOST_LOG(warning) << "Couldn't spawn ["sv << cmd << "]: System: "sv << ec.message(); } @@ -175,7 +175,7 @@ namespace proc { find_working_directory(_app.cmd, _env) : boost::filesystem::path(_app.working_dir); BOOST_LOG(info) << "Executing: ["sv << _app.cmd << "] in ["sv << working_dir << ']'; - _process = platf::run_command(_app.elevated, _app.cmd, working_dir, _env, _pipe.get(), ec, &_process_handle); + _process = platf::run_command(_app.elevated, true, _app.cmd, working_dir, _env, _pipe.get(), ec, &_process_handle); if (ec) { BOOST_LOG(warning) << "Couldn't run ["sv << _app.cmd << "]: System: "sv << ec.message(); return -1; @@ -223,7 +223,7 @@ namespace proc { find_working_directory(cmd.undo_cmd, _env) : boost::filesystem::path(_app.working_dir); BOOST_LOG(info) << "Executing Undo Cmd: ["sv << cmd.undo_cmd << ']'; - auto child = platf::run_command(cmd.elevated, cmd.undo_cmd, working_dir, _env, _pipe.get(), ec, nullptr); + auto child = platf::run_command(cmd.elevated, true, cmd.undo_cmd, working_dir, _env, _pipe.get(), ec, nullptr); if (ec) { BOOST_LOG(warning) << "System: "sv << ec.message();