Support waiting for child procs

Untested!
main
Peter Repukat 3 years ago
parent 1b920938c7
commit 8d9771f0ee

@ -20,6 +20,7 @@ limitations under the License.
#ifdef _WIN32 #ifdef _WIN32
#include <ShObjIdl.h> #include <ShObjIdl.h>
#include <atlbase.h> #include <atlbase.h>
#include <tlhelp32.h>
#endif #endif
#include "Settings.h" #include "Settings.h"
@ -47,26 +48,30 @@ void AppLauncher::launchApp(const std::wstring& path, const std::wstring& args)
void AppLauncher::update() void AppLauncher::update()
{ {
if (process_check_clock_.getElapsedTime().asSeconds() > 1 && !logged_process_died_) { if (process_check_clock_.getElapsedTime().asMilliseconds() > 250) {
#ifdef _WIN32 #ifdef _WIN32
if (process_info.dwProcessId > 0) { if (launched_pid_ > 0) {
if (!IsProcessRunning(process_info.dwProcessId)) { if (Settings::launch.waitForChildProcs) {
spdlog::info("Launched App with PID \"{}\" died", process_info.dwProcessId); getChildPids(launched_pid_);
if (Settings::launch.closeOnExit) {
spdlog::info("Configured to close on exit. Shutting down..");
shutdown_();
}
logged_process_died_ = true;
} }
} if (!IsProcessRunning(launched_pid_)) {
if (uwp_pid_ > 0) { spdlog::info("Launched App with PID \"{}\" died", launched_pid_);
if (!IsProcessRunning(uwp_pid_)) { if (Settings::launch.closeOnExit && !Settings::launch.waitForChildProcs) {
spdlog::info("Launched App with PID \"{}\" died", uwp_pid_);
if (Settings::launch.closeOnExit) {
spdlog::info("Configured to close on exit. Shutting down..."); spdlog::info("Configured to close on exit. Shutting down...");
shutdown_(); shutdown_();
} }
logged_process_died_ = true; launched_pid_ = 0;
}
}
if (Settings::launch.waitForChildProcs) {
std::erase_if(child_pids_, [](auto pid) {
const auto running = IsProcessRunning(pid);
spdlog::info("Child process with PID \"{}\" died", pid);
return !running;
});
if (Settings::launch.closeOnExit && child_pids_.empty() && launched_pid_ == 0) {
spdlog::info("Configured to close on all children exit. Shutting down...");
shutdown_();
} }
} }
#endif #endif
@ -83,6 +88,7 @@ void AppLauncher::close()
} }
#endif #endif
} }
#ifdef _WIN32 #ifdef _WIN32
bool AppLauncher::IsProcessRunning(DWORD pid) bool AppLauncher::IsProcessRunning(DWORD pid)
{ {
@ -93,6 +99,21 @@ bool AppLauncher::IsProcessRunning(DWORD pid)
CloseHandle(process); CloseHandle(process);
return ret == WAIT_TIMEOUT; return ret == WAIT_TIMEOUT;
} }
void AppLauncher::getChildPids(DWORD parent_pid)
{
HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = {0};
pe.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hp, &pe)) {
do {
if (pe.th32ParentProcessID == parent_pid) {
child_pids_.insert(pe.th32ProcessID);
}
} while (Process32Next(hp, &pe));
}
CloseHandle(hp);
}
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
@ -147,6 +168,7 @@ void AppLauncher::launchWin32App(const std::wstring& path, const std::wstring& a
&process_info)) { &process_info)) {
//spdlog::info(L"Started Program: \"{}\" in directory: \"{}\"", native_seps_path, launch_dir); //spdlog::info(L"Started Program: \"{}\" in directory: \"{}\"", native_seps_path, launch_dir);
spdlog::info(L"Started Program: \"{}\"", native_seps_path); spdlog::info(L"Started Program: \"{}\"", native_seps_path);
launched_pid_ = process_info.dwProcessId;
} }
else { else {
//spdlog::error(L"Couldn't start program: \"{}\" in directory: \"{}\"", native_seps_path, launch_dir); //spdlog::error(L"Couldn't start program: \"{}\" in directory: \"{}\"", native_seps_path, launch_dir);
@ -177,7 +199,7 @@ void AppLauncher::launchUWPApp(const LPCWSTR package_full_name, const std::wstri
} }
// Launch the app // Launch the app
result = sp_app_activation_manager->ActivateApplication(package_full_name, args.empty() ? nullptr : args.data(), AO_NONE, &uwp_pid_); result = sp_app_activation_manager->ActivateApplication(package_full_name, args.empty() ? nullptr : args.data(), AO_NONE, &launched_pid_);
if (!SUCCEEDED(result)) { if (!SUCCEEDED(result)) {
spdlog::error("ActivateApplication failed: Code {}", result); spdlog::error("ActivateApplication failed: Code {}", result);
} else { } else {

@ -21,6 +21,7 @@ limitations under the License.
#endif #endif
#include <functional> #include <functional>
#include <string> #include <string>
#include <unordered_set>
#include <SFML/System/Clock.hpp> #include <SFML/System/Clock.hpp>
class AppLauncher { class AppLauncher {
@ -35,10 +36,10 @@ private:
std::function<void()> shutdown_; std::function<void()> shutdown_;
sf::Clock process_check_clock_; sf::Clock process_check_clock_;
bool logged_process_died_ = false;
#ifdef _WIN32 #ifdef _WIN32
static bool IsProcessRunning(DWORD pid); static bool IsProcessRunning(DWORD pid);
void getChildPids(DWORD parent_pid);
// Valve also hooks "CreateProcess" // Valve also hooks "CreateProcess"
// Unpatch that so that launched programs don't also get hooked... // Unpatch that so that launched programs don't also get hooked...
@ -48,6 +49,7 @@ private:
void launchUWPApp(LPCWSTR package_full_name, const std::wstring& args = L""); void launchUWPApp(LPCWSTR package_full_name, const std::wstring& args = L"");
STARTUPINFO info{sizeof(info)}; STARTUPINFO info{sizeof(info)};
PROCESS_INFORMATION process_info{}; PROCESS_INFORMATION process_info{};
DWORD uwp_pid_ = 0; DWORD launched_pid_ = 0;
std::unordered_set<DWORD> child_pids_;
#endif #endif
}; };

@ -51,8 +51,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,0,2,003003750647 FILEVERSION 0,0,2,005001092093
PRODUCTVERSION 0,0,2,003003750647 PRODUCTVERSION 0,0,2,005001092093
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -69,12 +69,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Peter Repukat - FlatspotSoftware" VALUE "CompanyName", "Peter Repukat - FlatspotSoftware"
VALUE "FileDescription", "GlosSI - SteamTarget" VALUE "FileDescription", "GlosSI - SteamTarget"
VALUE "FileVersion", "0.0.2.0-3-g375c647" VALUE "FileVersion", "0.0.2.0-5-g1b92093"
VALUE "InternalName", "GlosSITarget" VALUE "InternalName", "GlosSITarget"
VALUE "LegalCopyright", "Copyright (C) 2021 Peter Repukat - FlatspotSoftware" VALUE "LegalCopyright", "Copyright (C) 2021 Peter Repukat - FlatspotSoftware"
VALUE "OriginalFilename", "GlosSITarget.exe" VALUE "OriginalFilename", "GlosSITarget.exe"
VALUE "ProductName", "GlosSI" VALUE "ProductName", "GlosSI"
VALUE "ProductVersion", "0.0.2.0-3-g375c647" VALUE "ProductVersion", "0.0.2.0-5-g1b92093"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
@ -631,6 +631,10 @@ END

@ -29,6 +29,7 @@ inline struct Launch {
std::wstring launchPath; std::wstring launchPath;
std::wstring launchAppArgs; std::wstring launchAppArgs;
bool closeOnExit = true; bool closeOnExit = true;
bool waitForChildProcs = false;
bool isUWP = false; bool isUWP = false;
} launch; } launch;
@ -108,6 +109,7 @@ inline void Parse(std::string arg1)
safeWStringParse(launchconf, "launchPath", launch.launchPath); safeWStringParse(launchconf, "launchPath", launch.launchPath);
safeWStringParse(launchconf, "launchAppArgs", launch.launchAppArgs); safeWStringParse(launchconf, "launchAppArgs", launch.launchAppArgs);
safeParseValue(launchconf, "closeOnExit", launch.closeOnExit); safeParseValue(launchconf, "closeOnExit", launch.closeOnExit);
safeParseValue(launchconf, "waitForChildProcs", launch.waitForChildProcs);
} }
if (auto devconf = json["devices"]; devconf.is_object()) { if (auto devconf = json["devices"]; devconf.is_object()) {

Loading…
Cancel
Save