From 360b362b7b4500052790f2d61ac8b367812ad8c2 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Wed, 21 Dec 2022 16:47:10 +0800 Subject: [PATCH] Moved command and process execution helpers to SHExecUtilities --- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 68 +----------- SHADE_Engine/src/Scripting/SHScriptEngine.h | 4 +- .../src/Tools/Utilities/SHExecUtilities.cpp | 103 ++++++++++++++++++ .../src/Tools/Utilities/SHExecUtilities.h | 84 ++++++++++++++ 4 files changed, 191 insertions(+), 68 deletions(-) create mode 100644 SHADE_Engine/src/Tools/Utilities/SHExecUtilities.cpp create mode 100644 SHADE_Engine/src/Tools/Utilities/SHExecUtilities.h diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 76a57242..b4f893d7 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -30,6 +30,7 @@ of DigiPen Institute of Technology is prohibited. #include "Scene/SHSceneEvents.h" #include "Assets/SHAssetMacros.h" +#include "Tools/Utilities/SHExecUtilities.h" namespace SHADE { @@ -189,11 +190,7 @@ namespace SHADE oss << "[ScriptEngine] Building " << (debug ? " debug " : "") << "Managed Script Assembly (" << MANAGED_SCRIPT_LIB_NAME << ")!"; SHLOG_INFO(oss.str()); oss.str(""); - const bool BUILD_SUCCESS = execProcess - ( - L"C:\\Windows\\system32\\cmd.exe", - L"/K \"" + generateBuildCommand(debug) + L" & exit\"" - ) == 0; + const bool BUILD_SUCCESS = SHExecUtilties::ExecBlockingCommand(generateBuildCommand(debug)) == 0; if (BUILD_SUCCESS) { // Copy to built dll to the working directory and replace @@ -315,7 +312,7 @@ namespace SHADE } // Open it - execProcessNoBlock + SHExecUtilties::ExecProcess ( L"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\Common7\\IDE\\devenv.exe", L"/Edit " + SHStringUtilities::StrToWstr(CSPROJ_PATH) @@ -626,65 +623,6 @@ namespace SHADE } } - DWORD SHScriptEngine::execProcess(const std::wstring& path, const std::wstring& args) - { - PROCESS_INFORMATION procInfo = execProcessNoBlock(path, args); - - // Wait for execution to end - DWORD status; - while (true) - { - const auto EXEC_SUCCESS = GetExitCodeProcess(procInfo.hProcess, &status); - if (!EXEC_SUCCESS) - { - auto err = GetLastError(); - std::ostringstream oss; - oss << "[ScriptEngine] Failed to query process. Error code: " << std::hex << err - << " (" << SHStringUtilities::GetWin32ErrorMessage(err) << ")"; - throw std::runtime_error(oss.str()); - } - - // Break only if process ends - if (status != STILL_ACTIVE) - { - CloseHandle(procInfo.hProcess); - CloseHandle(procInfo.hThread); - return status; - } - } - } - - PROCESS_INFORMATION SHScriptEngine::execProcessNoBlock(const std::wstring& path, const std::wstring& args) - { - STARTUPINFOW startInfo; - PROCESS_INFORMATION procInfo; - ZeroMemory(&startInfo, sizeof(startInfo)); - ZeroMemory(&procInfo, sizeof(procInfo)); - startInfo.cb = sizeof(startInfo); - - std::wstring argsWstr = args; - - // Start Process - const auto SUCCESS = CreateProcess - ( - path.data(), argsWstr.data(), - nullptr, nullptr, false, NULL, nullptr, nullptr, - &startInfo, &procInfo - ); - - // Error Check - if (!SUCCESS) - { - auto err = GetLastError(); - std::ostringstream oss; - oss << "[ScriptEngine] Failed to launch process. Error code: " << std::hex << err - << " (" << SHStringUtilities::GetWin32ErrorMessage(err) << ")"; - throw std::runtime_error(oss.str()); - } - - return procInfo; - } - std::wstring SHScriptEngine::generateBuildCommand(bool debug) { std::wostringstream oss; diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index 40efa042..d26b360e 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -1,5 +1,5 @@ /************************************************************************************//*! -\file ScriptEngine.h +\file SHScriptEngine.h \author Tng Kah Wei, kahwei.tng, 390009620 \par email: kahwei.tng\@digipen.edu \date Sep 17, 2021 @@ -324,8 +324,6 @@ namespace SHADE /// True if the file exists static bool fileExists(const std::filesystem::path& filePath); static bool copyFile(const std::filesystem::path& from, const std::filesystem::path& to, const std::filesystem::copy_options options) noexcept; - static DWORD execProcess(const std::wstring& path, const std::wstring& args); - static PROCESS_INFORMATION execProcessNoBlock(const std::wstring& path, const std::wstring& args); static std::wstring generateBuildCommand(bool debug); }; } diff --git a/SHADE_Engine/src/Tools/Utilities/SHExecUtilities.cpp b/SHADE_Engine/src/Tools/Utilities/SHExecUtilities.cpp new file mode 100644 index 00000000..c1bae764 --- /dev/null +++ b/SHADE_Engine/src/Tools/Utilities/SHExecUtilities.cpp @@ -0,0 +1,103 @@ +/************************************************************************************//*! +\file SHExecUtilities.cpp +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Dec 21, 2022 +\brief Contains the implementation for SHExecUtilities static class. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +// Precompiled Headers +#include +// Primary Header +#include "SHExecUtilities.h" +// Project Includes +#include "SHStringUtilities.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Process Execution Functions */ + /*-----------------------------------------------------------------------------------*/ + PROCESS_INFORMATION SHExecUtilties::ExecProcess(const std::wstring& path, const std::wstring& args) + { + STARTUPINFOW startInfo; + PROCESS_INFORMATION procInfo; + ZeroMemory(&startInfo, sizeof(startInfo)); + ZeroMemory(&procInfo, sizeof(procInfo)); + startInfo.cb = sizeof(startInfo); + + std::wstring argsWstr = args; + + // Start Process + const auto SUCCESS = CreateProcess + ( + path.data(), argsWstr.data(), + nullptr, nullptr, false, NULL, nullptr, nullptr, + &startInfo, &procInfo + ); + + // Error Check + if (!SUCCESS) + { + auto err = GetLastError(); + std::ostringstream oss; + oss << "[SHExecUtilties] Failed to launch process. Error code: " << std::hex << err + << " (" << SHStringUtilities::GetWin32ErrorMessage(err) << ")"; + throw std::runtime_error(oss.str()); + } + + return procInfo; + } + + DWORD SHExecUtilties::ExecBlockingProcess(const std::wstring& path, const std::wstring& args) + { + PROCESS_INFORMATION procInfo = ExecProcess(path, args); + + // Wait for execution to end + DWORD status; + while (true) + { + const auto EXEC_SUCCESS = GetExitCodeProcess(procInfo.hProcess, &status); + if (!EXEC_SUCCESS) + { + auto err = GetLastError(); + std::ostringstream oss; + oss << "[SHExecUtilties] Failed to query process. Error code: " << std::hex << err + << " (" << SHStringUtilities::GetWin32ErrorMessage(err) << ")"; + throw std::runtime_error(oss.str()); + } + + // Break only if process ends + if (status != STILL_ACTIVE) + { + CloseHandle(procInfo.hProcess); + CloseHandle(procInfo.hThread); + return status; + } + } + } + + /*-----------------------------------------------------------------------------------*/ + /* Command Execution Functions */ + /*-----------------------------------------------------------------------------------*/ + PROCESS_INFORMATION SHExecUtilties::ExecCommand(const std::wstring& command) + { + return ExecProcess + ( + L"C:\\Windows\\system32\\cmd.exe", + L"/K \"" + command + L" & exit\"" + ); + } + + DWORD SHExecUtilties::ExecBlockingCommand(const std::wstring& command) + { + return ExecBlockingProcess + ( + L"C:\\Windows\\system32\\cmd.exe", + L"/K \"" + command + L" & exit\"" + ); + } +} diff --git a/SHADE_Engine/src/Tools/Utilities/SHExecUtilities.h b/SHADE_Engine/src/Tools/Utilities/SHExecUtilities.h new file mode 100644 index 00000000..838cee41 --- /dev/null +++ b/SHADE_Engine/src/Tools/Utilities/SHExecUtilities.h @@ -0,0 +1,84 @@ +/************************************************************************************//*! +\file SHExecUtilties.h +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Dec 21, 2022 +\brief Contains the interface for SHExecUtilities class. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ + +// STL Includes +#include +// External Dependencies +#include + +namespace SHADE +{ + /// + /// Static class containing functions for executing external processes or commands. + /// + class SH_API SHExecUtilties final + { + public: + /*---------------------------------------------------------------------------------*/ + /* Process Execution Functions */ + /*---------------------------------------------------------------------------------*/ + /// + /// Executes a process at the specified path with the specified arguments. This call + /// does not wait for the process to finish executing. + /// + /// Path to the processs to start. + /// Arguments to pass to the process. + /// Information about the started process. + /// + /// Thrown if failed to start the process. + /// + static PROCESS_INFORMATION ExecProcess(const std::wstring& path, const std::wstring& args); + /// + /// Executes a process at the specified path with the specified arguments and waits + /// for that process to finish executing. + /// + /// Path to the processs to start. + /// Arguments to pass to the process. + /// Return value of the process. + /// + /// Thrown if failed to start the process. + /// + static DWORD ExecBlockingProcess(const std::wstring& path, const std::wstring& args); + + /*---------------------------------------------------------------------------------*/ + /* Command Execution Functions */ + /*---------------------------------------------------------------------------------*/ + /// + /// Executes a specified command in cmd. + /// This call does not wait for the command to finish executing. + /// + /// Command to execute. + /// + /// Information about the started cmd process that executes the command. + /// + /// + /// Thrown if failed to start the process. + /// + static PROCESS_INFORMATION ExecCommand(const std::wstring& command); + /// + /// Executes a specified command in cmd and waits for that process to finish + /// executing. + /// + /// Command to execute. + /// Return value of the process. + /// + /// Thrown if failed to start the process. + /// + static DWORD ExecBlockingCommand(const std::wstring& command); + + private: + /*-------------------------------------------------------------------------------*/ + /* Constructors/Destructors */ + /*-------------------------------------------------------------------------------*/ + SHExecUtilties() = delete; + }; +}