Added scripting quality of life features #299

Merged
Pycorax merged 10 commits from SP3-6-c-scripting into main 2023-01-01 12:37:10 +08:00
4 changed files with 191 additions and 68 deletions
Showing only changes of commit 360b362b7b - Show all commits

View File

@ -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;

View File

@ -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
/// <returns> True if the file exists </returns>
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);
};
}

View File

@ -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 <SHpch.h>
// 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\""
);
}
}

View File

@ -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 <string>
// External Dependencies
#include <Windows.h>
namespace SHADE
{
/// <summary>
/// Static class containing functions for executing external processes or commands.
/// </summary>
class SH_API SHExecUtilties final
{
public:
/*---------------------------------------------------------------------------------*/
/* Process Execution Functions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Executes a process at the specified path with the specified arguments. This call
/// does not wait for the process to finish executing.
/// </summary>
/// <param name="path">Path to the processs to start.</param>
/// <param name="args">Arguments to pass to the process.</param>
/// <returns>Information about the started process.</returns>
/// <exception cref="std::runtime_error">
/// Thrown if failed to start the process.
/// </exception>
static PROCESS_INFORMATION ExecProcess(const std::wstring& path, const std::wstring& args);
/// <summary>
/// Executes a process at the specified path with the specified arguments and waits
/// for that process to finish executing.
/// </summary>
/// <param name="path">Path to the processs to start.</param>
/// <param name="args">Arguments to pass to the process.</param>
/// <returns>Return value of the process.</returns>
/// <exception cref="std::runtime_error">
/// Thrown if failed to start the process.
/// </exception>
static DWORD ExecBlockingProcess(const std::wstring& path, const std::wstring& args);
/*---------------------------------------------------------------------------------*/
/* Command Execution Functions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Executes a specified command in cmd.
/// This call does not wait for the command to finish executing.
/// </summary>
/// <param name="command">Command to execute.</param>
/// <returns>
/// Information about the started cmd process that executes the command.
/// </returns>
/// <exception cref="std::runtime_error">
/// Thrown if failed to start the process.
/// </exception>
static PROCESS_INFORMATION ExecCommand(const std::wstring& command);
/// <summary>
/// Executes a specified command in cmd and waits for that process to finish
/// executing.
/// </summary>
/// <param name="command">Command to execute.</param>
/// <returns>Return value of the process.</returns>
/// <exception cref="std::runtime_error">
/// Thrown if failed to start the process.
/// </exception>
static DWORD ExecBlockingCommand(const std::wstring& command);
private:
/*-------------------------------------------------------------------------------*/
/* Constructors/Destructors */
/*-------------------------------------------------------------------------------*/
SHExecUtilties() = delete;
};
}