mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Added "Keep Native Console Open" option
This commit is contained in:
parent
fd3bd861ae
commit
8052066ab0
18 changed files with 423 additions and 41 deletions
|
@ -90,13 +90,13 @@ namespace System
|
|||
|
||||
static function void(StringView str) OutString = => OutString_Simple;
|
||||
|
||||
[CLink, CallingConvention(.Cdecl)]
|
||||
static extern void putchar(char8 c);
|
||||
public static extern void PutChar(char8 c);
|
||||
public static extern void ReopenHandles();
|
||||
|
||||
static void OutString_Simple(StringView str)
|
||||
{
|
||||
for (var c in str.RawChars)
|
||||
putchar(c);
|
||||
PutChar(c);
|
||||
}
|
||||
|
||||
static void OutString_Ex(StringView str)
|
||||
|
|
|
@ -1496,6 +1496,9 @@ namespace System
|
|||
[CLink, CallingConvention(.Stdcall)]
|
||||
public static extern IntBool GetExitCodeThread(Handle process, out int32 exitCode);
|
||||
|
||||
[Import("psapi.lib"), CLink, CallingConvention(.Stdcall)]
|
||||
public static extern int32 GetModuleFileNameExW(Handle process, Handle module, char16* filename, int32 size);
|
||||
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
public static extern int32 ResumeThread(Handle thread);
|
||||
|
||||
|
|
|
@ -181,6 +181,13 @@ namespace bf
|
|||
Beefy::String GetTypeName();
|
||||
};
|
||||
|
||||
class Console
|
||||
{
|
||||
public:
|
||||
BFRT_EXPORT static void PutChar(char c);
|
||||
BFRT_EXPORT static void ReopenHandles();
|
||||
};
|
||||
|
||||
class Exception : public Object
|
||||
{
|
||||
|
||||
|
|
|
@ -292,6 +292,26 @@ static void NTAPI TlsFreeFunc(void* ptr)
|
|||
gBfRtCallbacks.Thread_Exiting();
|
||||
}
|
||||
|
||||
void bf::System::Console::PutChar(char c)
|
||||
{
|
||||
putchar(c);
|
||||
}
|
||||
|
||||
void bf::System::Console::ReopenHandles()
|
||||
{
|
||||
FILE* fDummy;
|
||||
freopen_s(&fDummy, "CONOUT$", "w", stdout);
|
||||
freopen_s(&fDummy, "CONOUT$", "w", stderr);
|
||||
freopen_s(&fDummy, "CONIN$", "r", stdin);
|
||||
//
|
||||
// // std::wcout, std::wclog, std::wcerr, std::wcin
|
||||
HANDLE hConOut = CreateFileA("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
HANDLE hConIn = CreateFileA("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
|
||||
SetStdHandle(STD_ERROR_HANDLE, hConOut);
|
||||
SetStdHandle(STD_INPUT_HANDLE, hConIn);
|
||||
}
|
||||
|
||||
void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
|
||||
{
|
||||
BfpSystemInitFlags sysInitFlags = BfpSystemInitFlag_InstallCrashCatcher;
|
||||
|
|
|
@ -12,14 +12,20 @@ class Program
|
|||
BeefConConsoleProvider.Pipe mPipe ~ delete _;
|
||||
WinNativeConsoleProvider mProvider ~ delete _;
|
||||
int32 mPid;
|
||||
int32 mAttachedPid;
|
||||
Windows.ProcessHandle mAttachedProcess;
|
||||
String mAttachedName = new .() ~ delete _;
|
||||
int32 mConid;
|
||||
String mExecStr = new .() ~ delete _;
|
||||
SpawnedProcess mSpawnedProcess ~ delete _;
|
||||
|
||||
public ~this()
|
||||
{
|
||||
mSpawnedProcess.Kill();
|
||||
mSpawnedProcess.WaitFor();
|
||||
if (mSpawnedProcess != null)
|
||||
{
|
||||
mSpawnedProcess.Kill();
|
||||
mSpawnedProcess.WaitFor();
|
||||
}
|
||||
}
|
||||
|
||||
static mixin GET<T>(var ptr)
|
||||
|
@ -105,6 +111,16 @@ class Program
|
|||
case .Update:
|
||||
bool paused = GET!<bool>(ptr);
|
||||
mProvider.Update(paused);
|
||||
case .Attached:
|
||||
int32 pid = GET!<int32>(ptr);
|
||||
Process process = scope .();
|
||||
if (process.GetProcessById(pid) case .Ok)
|
||||
{
|
||||
mAttachedPid = pid;
|
||||
mAttachedName.Set(process.ProcessName);
|
||||
WinNativeConsoleProvider.SetConsoleTitleW(mAttachedName.ToScopedNativeWChar!());
|
||||
mAttachedProcess = Windows.OpenProcess(Windows.PROCESS_ALL_ACCESS, false, mAttachedPid);
|
||||
}
|
||||
default:
|
||||
}
|
||||
case .Err(let err):
|
||||
|
@ -113,22 +129,111 @@ class Program
|
|||
}
|
||||
}
|
||||
|
||||
public void ClearConsoleTitle()
|
||||
{
|
||||
WinNativeConsoleProvider.SetConsoleTitleW("BeefIDE Debug Console".ToScopedNativeWChar!());
|
||||
}
|
||||
|
||||
/*[CLink]
|
||||
static extern void* freopen (char8 * filename, char8 * mode, void* stream );
|
||||
[CLink]
|
||||
static extern void* stdout;*/
|
||||
|
||||
public void Run()
|
||||
{
|
||||
mPipe = new .();
|
||||
mPipe.Listen(mPid, mConid);
|
||||
|
||||
mProvider = new .();
|
||||
//mProvider.mHideNativeConsole = false;
|
||||
mProvider.mHideNativeConsole = !mExecStr.IsEmpty;
|
||||
mProvider.Attach();
|
||||
Console.ReopenHandles();
|
||||
|
||||
ProcessStartInfo procInfo = scope ProcessStartInfo();
|
||||
procInfo.UseShellExecute = false;
|
||||
procInfo.SetFileName(mExecStr);
|
||||
if (!mExecStr.IsEmpty)
|
||||
{
|
||||
ProcessStartInfo procInfo = scope ProcessStartInfo();
|
||||
procInfo.UseShellExecute = false;
|
||||
procInfo.SetFileName(mExecStr);
|
||||
|
||||
mSpawnedProcess = new SpawnedProcess();
|
||||
if (mSpawnedProcess.Start(procInfo) case .Err)
|
||||
return;
|
||||
mSpawnedProcess = new SpawnedProcess();
|
||||
if (mSpawnedProcess.Start(procInfo) case .Err)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearConsoleTitle();
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Check BeefIDE process
|
||||
{
|
||||
var process = Platform.BfpProcess_GetById(null, mPid, null);
|
||||
if (process == null)
|
||||
{
|
||||
Console.Error.WriteLine("Process closed");
|
||||
return;
|
||||
}
|
||||
Platform.BfpProcess_Release(process);
|
||||
}
|
||||
|
||||
MessageLoop();
|
||||
|
||||
if (mPipe.mFailed)
|
||||
{
|
||||
if (mSpawnedProcess == null)
|
||||
{
|
||||
DeleteAndNullify!(mPipe);
|
||||
mPipe = new .();
|
||||
mPipe.Listen(mPid, mConid);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mPipe.mConnected)
|
||||
Thread.Sleep(20);
|
||||
|
||||
if (mSpawnedProcess != null)
|
||||
{
|
||||
if (mSpawnedProcess.WaitFor(0))
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAttachedPid != 0)
|
||||
{
|
||||
if ((Windows.GetExitCodeProcess(mAttachedProcess, var exitCode)) && (exitCode != 259))
|
||||
{
|
||||
ClearConsoleTitle();
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(scope $"{mAttachedName} (process {mAttachedPid}) exited with code {exitCode}.");
|
||||
Console.WriteLine("Press any key to close this window...");
|
||||
|
||||
mAttachedProcess.Close();
|
||||
mAttachedProcess = default;
|
||||
mAttachedPid = 0;
|
||||
mAttachedName.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
if ((mSpawnedProcess == null) && (mAttachedPid == 0))
|
||||
{
|
||||
if (Console.KeyAvailable)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*public void RunHost()
|
||||
{
|
||||
mPipe = new .();
|
||||
mPipe.Listen(mPid, 0);
|
||||
|
||||
|
||||
|
||||
WinNativeConsoleProvider.AllocConsole();
|
||||
WinNativeConsoleProvider.SetConsoleTitleW("BeefIDE Debug Console".ToScopedNativeWChar!());
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
@ -146,26 +251,32 @@ class Program
|
|||
|
||||
if (!mPipe.mConnected)
|
||||
Thread.Sleep(20);
|
||||
|
||||
if (mSpawnedProcess.WaitFor(0))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
public static int Main(String[] args)
|
||||
{
|
||||
if (args.Count < 2)
|
||||
if (args.Count < 1)
|
||||
{
|
||||
Console.Error.WriteLine("Usage: BeefCon <pid> <conid> <exe>");
|
||||
Console.Error.WriteLine("Usage: BeefCon <pid> [conid] [exe]");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Program pg = scope .();
|
||||
pg.mPid = int32.Parse(args[0]);
|
||||
pg.mConid = int32.Parse(args[1]);
|
||||
pg.mExecStr.Set(args[2]);
|
||||
pg.Run();
|
||||
|
||||
if (args.Count >= 3)
|
||||
{
|
||||
pg.mPid = int32.Parse(args[0]);
|
||||
pg.mConid = int32.Parse(args[1]);
|
||||
pg.mExecStr.Set(args[2]);
|
||||
pg.Run();
|
||||
}
|
||||
else
|
||||
{
|
||||
pg.mPid = int32.Parse(args[0]);
|
||||
pg.mConid = -Process.CurrentId;
|
||||
pg.Run();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -1500,7 +1500,7 @@ BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetProcessName(BfpProcess* process, char
|
|||
OUTRESULT(BfpProcessResult_UnknownError);
|
||||
return;
|
||||
}
|
||||
WCHAR wName[MAX_PATH];
|
||||
WCHAR wName[MAX_PATH] = { 0 };
|
||||
::GetModuleFileNameExW(hProc, NULL, wName, MAX_PATH);
|
||||
::CloseHandle(hProc);
|
||||
String name = UTF8Encode(wName);
|
||||
|
|
|
@ -270,7 +270,7 @@ namespace IDE.Debugger
|
|||
static extern char8* Debugger_GetCollectionContinuation(char8* continuationData, int32 callStackIdx, int32 count);
|
||||
|
||||
[CallingConvention(.Stdcall),CLink]
|
||||
static extern void Debugger_ForegroundTarget();
|
||||
static extern void Debugger_ForegroundTarget(int32 altProcessId);
|
||||
|
||||
[CallingConvention(.Stdcall),CLink]
|
||||
static extern void CallStack_Update();
|
||||
|
@ -314,6 +314,9 @@ namespace IDE.Debugger
|
|||
[CallingConvention(.Stdcall),CLink]
|
||||
static extern char8* Debugger_GetProcessInfo();
|
||||
|
||||
[CallingConvention(.Stdcall),CLink]
|
||||
static extern int32 Debugger_GetProcessId();
|
||||
|
||||
[CallingConvention(.Stdcall),CLink]
|
||||
static extern char8* Debugger_GetThreadInfo();
|
||||
|
||||
|
@ -912,9 +915,9 @@ namespace IDE.Debugger
|
|||
outVal.Append(result);
|
||||
}
|
||||
|
||||
public void ForegroundTarget()
|
||||
public void ForegroundTarget(int32 altProcessId)
|
||||
{
|
||||
Debugger_ForegroundTarget();
|
||||
Debugger_ForegroundTarget(altProcessId);
|
||||
}
|
||||
|
||||
public void UpdateCallStack()
|
||||
|
@ -1079,6 +1082,13 @@ namespace IDE.Debugger
|
|||
outProcessInfo.Append(strPtr);
|
||||
}
|
||||
|
||||
public int32 GetProcessId()
|
||||
{
|
||||
if (!mIsRunning)
|
||||
return 0;
|
||||
return Debugger_GetProcessId();
|
||||
}
|
||||
|
||||
public void GetThreadInfo(String outThreadInfo)
|
||||
{
|
||||
if (!mIsRunning)
|
||||
|
|
|
@ -426,8 +426,15 @@ namespace IDE
|
|||
public int mSampleRate;
|
||||
}
|
||||
|
||||
class OpenDebugConsoleCmd : ExecutionCmd
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
class StartDebugCmd : ExecutionCmd
|
||||
{
|
||||
public bool mConnectedToConsole;
|
||||
public int32 mConsoleProcessId;
|
||||
public bool mWasCompiled;
|
||||
public bool mHotCompileEnabled;
|
||||
|
||||
|
@ -9248,6 +9255,73 @@ namespace IDE
|
|||
}
|
||||
}
|
||||
|
||||
if (let startDebugCmd = next as StartDebugCmd)
|
||||
{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
if ((mSettings.mDebugConsoleKind == .Native) && (mSettings.mKeepNativeConsoleOpen))
|
||||
{
|
||||
if (!startDebugCmd.mConnectedToConsole)
|
||||
{
|
||||
if (startDebugCmd.mConsoleProcessId == 0)
|
||||
{
|
||||
int32 processId = 0;
|
||||
|
||||
List<Process> processList = scope .();
|
||||
Process.GetProcesses(processList);
|
||||
defer processList.ClearAndDeleteItems();
|
||||
|
||||
for (var process in processList)
|
||||
{
|
||||
if ((process.ProcessName.Contains("BeefCon.exe")) || (process.ProcessName.Contains("BeefCon_d.exe")))
|
||||
{
|
||||
var title = process.GetMainWindowTitle(.. scope .());
|
||||
if (title.EndsWith("Debug Console"))
|
||||
{
|
||||
processId = process.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (processId == 0)
|
||||
{
|
||||
var beefConExe = scope $"{gApp.mInstallDir}/BeefCon.exe";
|
||||
|
||||
ProcessStartInfo procInfo = scope ProcessStartInfo();
|
||||
procInfo.UseShellExecute = false;
|
||||
procInfo.SetFileName(beefConExe);
|
||||
procInfo.SetArguments(scope $"{Process.CurrentId}");
|
||||
procInfo.ActivateWindow = false;
|
||||
|
||||
var process = scope SpawnedProcess();
|
||||
if (process.Start(procInfo) case .Ok)
|
||||
{
|
||||
processId = (.)process.ProcessId;
|
||||
}
|
||||
}
|
||||
|
||||
startDebugCmd.mConsoleProcessId = processId;
|
||||
}
|
||||
|
||||
if (startDebugCmd.mConsoleProcessId != 0)
|
||||
{
|
||||
if (WinNativeConsoleProvider.AttachConsole(startDebugCmd.mConsoleProcessId))
|
||||
{
|
||||
// Worked
|
||||
WinNativeConsoleProvider.ClearConsole();
|
||||
mConsolePanel.mBeefConAttachState = .Attached(startDebugCmd.mConsoleProcessId);
|
||||
startDebugCmd.mConnectedToConsole = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep trying to attach
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
defer delete next;
|
||||
mExecutionQueue.RemoveAt(0);
|
||||
|
||||
|
@ -9336,6 +9410,19 @@ namespace IDE
|
|||
}
|
||||
else
|
||||
OutputLine("Failed to start debugger");
|
||||
|
||||
/*#if BF_PLATFORM_WINDOWS
|
||||
if ((mSettings.mDebugConsoleKind == .Native) && (mSettings.mKeepNativeConsoleOpen))
|
||||
{
|
||||
BeefConConsoleProvider.Pipe pipe = scope .();
|
||||
//pipe.Connect(Process.CurrentId, )
|
||||
pipe.Connect(123, -startDebugCmd.mConsoleProcessId).IgnoreError();
|
||||
|
||||
pipe.StartMessage(.Attached);
|
||||
pipe.Stream.Write((int32)mDebugger.GetProcessId());
|
||||
pipe.EndMessage();
|
||||
}
|
||||
#endif*/
|
||||
}
|
||||
}
|
||||
else if (next is ExecutionQueueCmd)
|
||||
|
@ -13781,7 +13868,12 @@ namespace IDE
|
|||
if (mForegroundTargetCountdown > 0)
|
||||
{
|
||||
if ((--mForegroundTargetCountdown == 0) && (mDebugger.mIsRunning))
|
||||
mDebugger.ForegroundTarget();
|
||||
{
|
||||
if (mConsolePanel.mBeefConAttachState case .Connected(let processId))
|
||||
mDebugger.ForegroundTarget(processId);
|
||||
else
|
||||
mDebugger.ForegroundTarget(0);
|
||||
}
|
||||
}
|
||||
|
||||
if ((mDebugger != null) && (mExecutionPaused) && (mDebugger.mIsRunning))
|
||||
|
@ -13845,6 +13937,33 @@ namespace IDE
|
|||
DeleteAndNullify!(mLaunchData);
|
||||
|
||||
mErrorsPanel?.UpdateAlways();
|
||||
|
||||
if ((mConsolePanel != null) && (mConsolePanel.mBeefConAttachState case .Attached(let consoleProcessId)))
|
||||
{
|
||||
if (!mDebugger.mIsRunning)
|
||||
{
|
||||
mConsolePanel.Detach();
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 debugProcessId = mDebugger.GetProcessId();
|
||||
if (debugProcessId != 0)
|
||||
{
|
||||
BeefConConsoleProvider.Pipe pipe = scope .();
|
||||
pipe.Connect(Process.CurrentId, -consoleProcessId).IgnoreError();
|
||||
//pipe.Connect(Process.CurrentId, )
|
||||
//pipe.Connect(123, -consoleProcessId).IgnoreError();
|
||||
|
||||
pipe.StartMessage(.Attached);
|
||||
pipe.Stream.Write(debugProcessId);
|
||||
pipe.EndMessage();
|
||||
mConsolePanel.Detach();
|
||||
|
||||
mConsolePanel.mBeefConAttachState = .Connected(consoleProcessId);
|
||||
mDebugger.ForegroundTarget(consoleProcessId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowPassOutput(BfPassInstance bfPassInstance)
|
||||
|
|
|
@ -1122,6 +1122,7 @@ namespace IDE
|
|||
public String mWindowsTerminal = new .("Powershell") ~ delete _;
|
||||
public ConsoleKind mDebugConsoleKind;
|
||||
public bool mAlwaysEnableConsole;
|
||||
public bool mKeepNativeConsoleOpen;
|
||||
public String mEmscriptenPath = new .() ~ delete _;
|
||||
public bool mEnableDevMode;
|
||||
public TutorialsFinished mTutorialsFinished = .();
|
||||
|
@ -1184,6 +1185,7 @@ namespace IDE
|
|||
sd.Add("WindowsTerminal", mWindowsTerminal);
|
||||
sd.Add("DebugConsole", mDebugConsoleKind);
|
||||
sd.Add("AlwaysEnableConsole", mAlwaysEnableConsole);
|
||||
sd.Add("KeepNativeConsoleOpen", mKeepNativeConsoleOpen);
|
||||
}
|
||||
using (sd.CreateObject("Wasm"))
|
||||
sd.Add("EmscriptenPath", mEmscriptenPath);
|
||||
|
@ -1279,6 +1281,7 @@ namespace IDE
|
|||
sd.Get("WindowsTerminal", mWindowsTerminal);
|
||||
mDebugConsoleKind = sd.GetEnum<ConsoleKind>("DebugConsole", .Native);
|
||||
mAlwaysEnableConsole = sd.GetBool("AlwaysEnableConsole");
|
||||
mKeepNativeConsoleOpen = sd.GetBool("KeepNativeConsoleOpen");
|
||||
}
|
||||
using (sd.Open("Wasm"))
|
||||
sd.Get("EmscriptenPath", mEmscriptenPath);
|
||||
|
|
|
@ -281,6 +281,13 @@ class ConsolePanel : Panel
|
|||
}
|
||||
}
|
||||
|
||||
public enum BeefConAttachState
|
||||
{
|
||||
case None;
|
||||
case Attached(int32 processId);
|
||||
case Connected(int32 processId);
|
||||
}
|
||||
|
||||
public ConsoleProvider mConsoleProvider ~ delete _;
|
||||
public DarkCheckBox mMousePassthroughCB;
|
||||
public DarkCheckBox mPauseCB;
|
||||
|
@ -290,6 +297,7 @@ class ConsolePanel : Panel
|
|||
public int32 mCellHeight;
|
||||
public (Position start, Position end)? mSelection;
|
||||
public Position? mClickPos;
|
||||
public BeefConAttachState mBeefConAttachState;
|
||||
|
||||
public bool Paused
|
||||
{
|
||||
|
@ -781,6 +789,14 @@ class ConsolePanel : Panel
|
|||
|
||||
public void Detach()
|
||||
{
|
||||
if (mBeefConAttachState case .Attached)
|
||||
{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
WinNativeConsoleProvider.FreeConsole();
|
||||
#endif
|
||||
mBeefConAttachState = .None;
|
||||
}
|
||||
|
||||
if (!mConsoleProvider.Attached)
|
||||
return;
|
||||
mConsoleProvider.Detach();
|
||||
|
|
|
@ -181,6 +181,7 @@ namespace IDE.ui
|
|||
AddPropertiesItem(category, "Windows Terminal", "mWindowsTerminal");
|
||||
AddPropertiesItem(category, "Debug Console", "mDebugConsoleKind");
|
||||
AddPropertiesItem(category, "Always Enable Console", "mAlwaysEnableConsole");
|
||||
AddPropertiesItem(category, "Keep Native Console Open", "mKeepNativeConsoleOpen");
|
||||
category.Open(true, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -250,10 +250,13 @@ class WinNativeConsoleProvider : ConsoleProvider
|
|||
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
public static extern void AllocConsole();
|
||||
public static extern Windows.IntBool AllocConsole();
|
||||
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
public static extern void AttachConsole(int processId);
|
||||
public static extern void SetConsoleTitleW(char16* title);
|
||||
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
public static extern Windows.IntBool AttachConsole(int processId);
|
||||
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
public static extern void FreeConsole();
|
||||
|
@ -290,6 +293,15 @@ class WinNativeConsoleProvider : ConsoleProvider
|
|||
|
||||
[CLink]
|
||||
public static extern Windows.IntBool ReadConsoleInputW(Windows.Handle handle, INPUT_RECORD* eventsPtr, int32 eventCount, out int32 numEventsRead);
|
||||
|
||||
[CLink]
|
||||
public static extern Windows.IntBool SetConsoleCursorPosition(Windows.Handle handle, POINT pos);
|
||||
|
||||
[CLink]
|
||||
public static extern Windows.IntBool FillConsoleOutputCharacterW(Windows.Handle handle, char16 char, int32 length, POINT writeCoord, out int32 numCharsWritten);
|
||||
|
||||
[CLink]
|
||||
public static extern Windows.IntBool FillConsoleOutputAttribute(Windows.Handle handle, uint16 attribute, int32 length, POINT writeCoord, out int32 numCharsWritten);
|
||||
#endif
|
||||
|
||||
ScreenInfo mScreenInfo ~ delete _;
|
||||
|
@ -789,6 +801,58 @@ class WinNativeConsoleProvider : ConsoleProvider
|
|||
{
|
||||
return (mScreenInfo != null) ? mScreenInfo.mColorTable[i] : 0xFF000000;
|
||||
}
|
||||
|
||||
public static void ClearConsole()
|
||||
{
|
||||
var outHandle = Console.[Friend]GetStdHandle(Console.STD_OUTPUT_HANDLE);
|
||||
|
||||
POINT coordScreen = default; // home for the cursor
|
||||
int32 cCharsWritten;
|
||||
CONSOLE_SCREEN_BUFFER_INFOEX csbi = default;
|
||||
csbi.mSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
|
||||
|
||||
// Get the number of character cells in the current buffer.
|
||||
if (!GetConsoleScreenBufferInfoEx(outHandle, ref csbi))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let dwConSize = (int32)csbi.mWidth * csbi.mHeight;
|
||||
|
||||
// Fill the entire screen with blanks.
|
||||
if (!FillConsoleOutputCharacterW(outHandle, // Handle to console screen buffer
|
||||
' ', // Character to write to the buffer
|
||||
dwConSize, // Number of cells to write
|
||||
coordScreen, // Coordinates of first cell
|
||||
out cCharsWritten)) // Receive number of characters written
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current text attribute.
|
||||
if (!GetConsoleScreenBufferInfoEx(outHandle, ref csbi))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the buffer's attributes accordingly.
|
||||
if (!FillConsoleOutputAttribute(outHandle, // Handle to console screen buffer
|
||||
csbi.wAttributes, // Character attributes to use
|
||||
dwConSize, // Number of cells to set attribute
|
||||
coordScreen, // Coordinates of first cell
|
||||
out cCharsWritten)) // Receive number of characters written
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Put the cursor at its home coordinates.
|
||||
SetConsoleCursorPosition(outHandle, coordScreen);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
ClearConsole();
|
||||
}
|
||||
}
|
||||
|
||||
class BeefConConsoleProvider : ConsoleProvider
|
||||
|
@ -807,7 +871,8 @@ class BeefConConsoleProvider : ConsoleProvider
|
|||
MouseUp,
|
||||
MouseWheel,
|
||||
ScrollTo,
|
||||
Update
|
||||
Update,
|
||||
Attached
|
||||
}
|
||||
|
||||
public class Pipe
|
||||
|
|
|
@ -409,7 +409,7 @@ void CeDebugger::ContinueDebugEvent()
|
|||
mCeMachine->mDebugEvent.Set();
|
||||
}
|
||||
|
||||
void CeDebugger::ForegroundTarget()
|
||||
void CeDebugger::ForegroundTarget(int altProcessId)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -4361,6 +4361,11 @@ String CeDebugger::GetProcessInfo()
|
|||
return String();
|
||||
}
|
||||
|
||||
int CeDebugger::GetProcessId()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
DebugVisualizerEntry* CeDebugger::FindVisualizerForType(BfType* dbgType, Array<String>* wildcardCaptures)
|
||||
{
|
||||
auto ceModule = mCeMachine->mCeModule;
|
||||
|
|
|
@ -324,7 +324,7 @@ public:
|
|||
virtual String GetDbgAllocInfo() override;
|
||||
virtual void Update() override;
|
||||
virtual void ContinueDebugEvent() override;
|
||||
virtual void ForegroundTarget() override;
|
||||
virtual void ForegroundTarget(int altProcessId) override;
|
||||
virtual Breakpoint* CreateBreakpoint(const StringImpl& fileName, int lineNum, int wantColumn, int instrOffset) override;
|
||||
virtual Breakpoint* CreateMemoryBreakpoint(intptr addr, int byteCount) override;
|
||||
virtual Breakpoint* CreateSymbolBreakpoint(const StringImpl& symbolName) override;
|
||||
|
@ -359,6 +359,7 @@ public:
|
|||
virtual String GetAutoLocals(int callStackIdx, bool showRegs) override;
|
||||
virtual String CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx) override;
|
||||
virtual String GetProcessInfo() override;
|
||||
virtual int GetProcessId() override;
|
||||
virtual String GetThreadInfo() override;
|
||||
virtual void SetActiveThread(int threadId) override;
|
||||
virtual int GetActiveThread() override;
|
||||
|
|
|
@ -1363,9 +1363,9 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetCollectionContinuation(const char*
|
|||
return outString.c_str();
|
||||
}
|
||||
|
||||
BF_EXPORT void BF_CALLTYPE Debugger_ForegroundTarget()
|
||||
BF_EXPORT void BF_CALLTYPE Debugger_ForegroundTarget(int altProcessId)
|
||||
{
|
||||
gDebugger->ForegroundTarget();
|
||||
gDebugger->ForegroundTarget(altProcessId);
|
||||
|
||||
//BOOL worked = EnumThreadWindows(gDebugger->mProcessInfo.dwThreadId, WdEnumWindowsProc, 0);
|
||||
//BF_ASSERT(worked);
|
||||
|
@ -1378,6 +1378,11 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetProcessInfo()
|
|||
return outString.c_str();
|
||||
}
|
||||
|
||||
BF_EXPORT int BF_CALLTYPE Debugger_GetProcessId()
|
||||
{
|
||||
return gDebugger->GetProcessId();
|
||||
}
|
||||
|
||||
BF_EXPORT const char* BF_CALLTYPE Debugger_GetThreadInfo()
|
||||
{
|
||||
String& outString = *gTLStrReturn.Get();
|
||||
|
|
|
@ -285,7 +285,7 @@ public:
|
|||
virtual String GetDbgAllocInfo() = 0;
|
||||
virtual void Update() = 0;
|
||||
virtual void ContinueDebugEvent() = 0;
|
||||
virtual void ForegroundTarget() = 0;
|
||||
virtual void ForegroundTarget(int altProcessId) = 0;
|
||||
virtual Breakpoint* CreateBreakpoint(const StringImpl& fileName, int lineNum, int wantColumn, int instrOffset) = 0;
|
||||
virtual Breakpoint* CreateMemoryBreakpoint(intptr addr, int byteCount) = 0;
|
||||
virtual Breakpoint* CreateSymbolBreakpoint(const StringImpl& symbolName) = 0;
|
||||
|
@ -320,6 +320,7 @@ public:
|
|||
virtual String GetAutoLocals(int callStackIdx, bool showRegs) = 0;
|
||||
virtual String CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx) = 0;
|
||||
virtual String GetProcessInfo() = 0;
|
||||
virtual int GetProcessId() = 0;
|
||||
virtual String GetThreadInfo() = 0;
|
||||
virtual void SetActiveThread(int threadId) = 0;
|
||||
virtual int GetActiveThread() = 0;
|
||||
|
|
|
@ -3055,6 +3055,8 @@ void WinDebugger::ContinueDebugEvent()
|
|||
|
||||
static BOOL CALLBACK WdEnumWindowsProc(HWND hwnd, LPARAM lParam)
|
||||
{
|
||||
int wantProcessId = lParam;
|
||||
|
||||
HWND owner = GetWindow(hwnd, GW_OWNER);
|
||||
if (!IsWindowVisible(hwnd))
|
||||
return TRUE;
|
||||
|
@ -3062,7 +3064,7 @@ static BOOL CALLBACK WdEnumWindowsProc(HWND hwnd, LPARAM lParam)
|
|||
DWORD processId = 0;
|
||||
DWORD threadId = GetWindowThreadProcessId(hwnd, &processId);
|
||||
|
||||
if (processId != ((WinDebugger*)gDebugger)->mProcessInfo.dwProcessId)
|
||||
if (processId != wantProcessId)
|
||||
return TRUE;
|
||||
|
||||
while (true)
|
||||
|
@ -3080,8 +3082,12 @@ static BOOL CALLBACK WdEnumWindowsProc(HWND hwnd, LPARAM lParam)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void WinDebugger::ForegroundTarget()
|
||||
void WinDebugger::ForegroundTarget(int altProcessId)
|
||||
{
|
||||
int wantProcessId = altProcessId;
|
||||
if (wantProcessId == 0)
|
||||
wantProcessId = ((WinDebugger*)gDebugger)->mProcessInfo.dwProcessId;
|
||||
|
||||
HWND hwnd = ::GetForegroundWindow();
|
||||
if (hwnd != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
|
@ -3090,8 +3096,8 @@ void WinDebugger::ForegroundTarget()
|
|||
if (processId == ((WinDebugger*)gDebugger)->mProcessInfo.dwProcessId)
|
||||
return; // Already good
|
||||
}
|
||||
|
||||
EnumWindows(WdEnumWindowsProc, 0);
|
||||
|
||||
EnumWindows(WdEnumWindowsProc, wantProcessId);
|
||||
}
|
||||
|
||||
static int gFindLineDataAt = 0;
|
||||
|
@ -10977,6 +10983,14 @@ String WinDebugger::GetProcessInfo()
|
|||
return retStr;
|
||||
}
|
||||
|
||||
int WinDebugger::GetProcessId()
|
||||
{
|
||||
AutoCrit autoCrit(mDebugManager->mCritSect);
|
||||
if (!mThreadList.IsEmpty())
|
||||
return mThreadList[0]->mProcessId;
|
||||
return mDbgProcessId;
|
||||
}
|
||||
|
||||
String WinDebugger::GetThreadInfo()
|
||||
{
|
||||
AutoCrit autoCrit(mDebugManager->mCritSect);
|
||||
|
|
|
@ -598,7 +598,7 @@ public:
|
|||
virtual String GetDbgAllocInfo() override;
|
||||
virtual void Update() override;
|
||||
virtual void ContinueDebugEvent() override;
|
||||
virtual void ForegroundTarget() override;
|
||||
virtual void ForegroundTarget(int altProcessId) override;
|
||||
virtual Breakpoint* CreateBreakpoint(const StringImpl& fileName, int lineNum, int wantColumn, int instrOffset) override;
|
||||
virtual Breakpoint* CreateMemoryBreakpoint(intptr addr, int byteCount) override;
|
||||
virtual Breakpoint* CreateSymbolBreakpoint(const StringImpl& symbolName) override;
|
||||
|
@ -630,6 +630,7 @@ public:
|
|||
virtual String GetAutoLocals(int callStackIdx, bool showRegs) override;
|
||||
virtual String CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx) override;
|
||||
virtual String GetProcessInfo() override;
|
||||
virtual int GetProcessId() override;
|
||||
virtual String GetThreadInfo() override;
|
||||
virtual void SetActiveThread(int threadId) override;
|
||||
virtual int GetActiveThread() override;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue