diff --git a/BeefLibs/corlib/src/Platform.bf b/BeefLibs/corlib/src/Platform.bf index 38063ff3..75db820f 100644 --- a/BeefLibs/corlib/src/Platform.bf +++ b/BeefLibs/corlib/src/Platform.bf @@ -211,7 +211,9 @@ namespace System public enum BfpProcessResult : int32 { Ok = (int)Result.Ok, - InsufficientBuffer = (int)Result.InsufficientBuffer + NotFound = (int)Result.NotFound, + InsufficientBuffer = (int)Result.InsufficientBuffer, + UnknownError = (int)Result.UnknownError, } #if !BF_RUNTIME_DISABLE @@ -229,6 +231,9 @@ namespace System public static extern void BfpProcess_GetProcessName(BfpProcess* process, char8* outName, int32* inOutNameSize, BfpProcessResult* outResult); [CallingConvention(.Stdcall), CLink] public static extern int32 BfpProcess_GetProcessId(BfpProcess* process); + [CallingConvention(.Stdcall), CLink] + public static extern bool BfpProcess_WaitFor(BfpProcess* process, int waitMS, int* outExitCode, BfpProcessResult* outResult); + #else public static bool BfpProcess_IsRemoteMachine(char8* machineName) => Runtime.NotImplemented(); diff --git a/BeefTools/BeefCon/src/Program.bf b/BeefTools/BeefCon/src/Program.bf index e1a6d909..08a52b8e 100644 --- a/BeefTools/BeefCon/src/Program.bf +++ b/BeefTools/BeefCon/src/Program.bf @@ -19,6 +19,17 @@ class Program String mExecStr = new .() ~ delete _; SpawnedProcess mSpawnedProcess ~ delete _; + [CLink, CallingConvention(.Stdcall)] + public static extern Windows.IntBool AttachConsole(int processId); + + [CallingConvention(.Stdcall)] + function Windows.IntBool ConsoleCtrlHandler(int32 ctrlType); + [CLink, CallingConvention(.Stdcall)] + static extern Windows.IntBool SetConsoleCtrlHandler(ConsoleCtrlHandler handler, Windows.IntBool addHandler); + + [CLink, CallingConvention(.Stdcall)] + static extern Windows.IntBool GenerateConsoleCtrlEvent(uint32 dwCtrlEvent, uint32 dwProcessGroupId); + public ~this() { if (mSpawnedProcess != null) @@ -165,13 +176,21 @@ class Program // Check BeefIDE process if ((mPid != 123) || (!Debug.IsDebuggerPresent)) { + bool isProcessOpen = false; + var process = Platform.BfpProcess_GetById(null, mPid, null); - if (process == null) + if (process != null) + { + if (!Platform.BfpProcess_WaitFor(process, 0, null, null)) + isProcessOpen = true; + Platform.BfpProcess_Release(process); + } + + if (!isProcessOpen) { Console.Error.WriteLine("Process closed"); return; } - Platform.BfpProcess_Release(process); } MessageLoop(); @@ -267,6 +286,16 @@ class Program pg.mExecStr.Set(args[2]); pg.Run(); } + else if (args.Count >= 2) + { + pg.mPid = int32.Parse(args[0]); + if (args[1] == "kill") + { + AttachConsole(pg.mPid); + SetConsoleCtrlHandler(default, true); + GenerateConsoleCtrlEvent(/*CTRL_C_EVENT*/0, 0); + } + } else { pg.mPid = int32.Parse(args[0]); diff --git a/BeefySysLib/platform/PlatformInterface.h b/BeefySysLib/platform/PlatformInterface.h index 55daaf42..6abda725 100644 --- a/BeefySysLib/platform/PlatformInterface.h +++ b/BeefySysLib/platform/PlatformInterface.h @@ -180,6 +180,7 @@ BFP_EXPORT bool BFP_CALLTYPE BfpProcess_IsRemoteMachine(const char* machineName) BFP_EXPORT BfpProcess* BFP_CALLTYPE BfpProcess_GetById(const char* machineName, int processId, BfpProcessResult* outResult); BFP_EXPORT void BFP_CALLTYPE BfpProcess_Enumerate(const char* machineName, BfpProcess** outProcesses, int* inOutProcessesSize, BfpProcessResult* outResult); BFP_EXPORT void BFP_CALLTYPE BfpProcess_Release(BfpProcess* process); +BFP_EXPORT int BFP_CALLTYPE BfpProcess_GetExitCode(BfpProcess* process, BfpProcessResult* outResult); BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetMainWindowTitle(BfpProcess* process, char* outTitle, int* inOutTitleSize, BfpProcessResult* outResult); BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetProcessName(BfpProcess* process, char* outName, int* inOutNameSize, BfpProcessResult* outResult); BFP_EXPORT int BFP_CALLTYPE BfpProcess_GetProcessId(BfpProcess* process); diff --git a/BeefySysLib/platform/posix/PosixCommon.cpp b/BeefySysLib/platform/posix/PosixCommon.cpp index aa44a5a3..e108f0a9 100644 --- a/BeefySysLib/platform/posix/PosixCommon.cpp +++ b/BeefySysLib/platform/posix/PosixCommon.cpp @@ -858,6 +858,11 @@ BFP_EXPORT void BFP_CALLTYPE BfpProcess_Release(BfpProcess* process) NOT_IMPL; } +BFP_EXPORT bool BFP_CALLTYPE BfpProcess_WaitFor(BfpProcess* process, int waitMS, int* outExitCode, BfpProcessResult* outResult) +{ + NOT_IMPL; +} + BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetMainWindowTitle(BfpProcess* process, char* outTitle, int* inOutTitleSize, BfpProcessResult* outResult) { NOT_IMPL; diff --git a/BeefySysLib/platform/win/Platform.cpp b/BeefySysLib/platform/win/Platform.cpp index bee070f6..cd11f266 100644 --- a/BeefySysLib/platform/win/Platform.cpp +++ b/BeefySysLib/platform/win/Platform.cpp @@ -1285,7 +1285,15 @@ struct BfpProcess { int mProcessId; SYSTEM_PROCESS_INFORMATION* mInfo; + HANDLE mProcess; String mImageName; + + BfpProcess() + { + mProcessId = -1; + mInfo = NULL; + mProcess = 0; + } }; BFP_EXPORT bool BFP_CALLTYPE BfpProcess_IsRemoteMachine(const char* machineName) @@ -1295,16 +1303,16 @@ BFP_EXPORT bool BFP_CALLTYPE BfpProcess_IsRemoteMachine(const char* machineName) BFP_EXPORT BfpProcess* BFP_CALLTYPE BfpProcess_GetById(const char* machineName, int processId, BfpProcessResult* outResult) { - HANDLE hProc = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processId); + HANDLE hProc = ::OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, processId); if (hProc == NULL) { OUTRESULT(BfpProcessResult_NotFound); return NULL; - } - ::CloseHandle(hProc); + } BfpProcess* process = new BfpProcess(); process->mProcessId = processId; + process->mProcess = hProc; process->mInfo = NULL; return process; } @@ -1395,9 +1403,34 @@ BFP_EXPORT void BFP_CALLTYPE BfpProcess_Release(BfpProcess* process) { if (process->mInfo != NULL) free(process->mInfo); + if (process->mProcess != NULL) + ::CloseHandle(process->mProcess); delete process; } +BFP_EXPORT bool BFP_CALLTYPE BfpProcess_WaitFor(BfpProcess* process, int waitMS, int* outExitCode, BfpProcessResult* outResult) +{ + if (process->mProcess == NULL) + { + OUTRESULT(BfpProcessResult_NotFound); + return false; + } + + if (::WaitForSingleObject(process->mProcess, waitMS) != WAIT_OBJECT_0) + { + OUTRESULT(BfpProcessResult_NotFound); + return false; + } + + DWORD errorCode = 0; + GetExitCodeProcess(process->mProcess, &errorCode); + if (outExitCode != NULL) + *outExitCode = (int)errorCode; + + OUTRESULT(BfpProcessResult_Ok); + return true; +} + //struct EnumWndData //{ // HWND mBestHandle;