1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Added "Keep Native Console Open" option

This commit is contained in:
Brian Fiete 2024-07-24 09:41:08 +02:00
parent fd3bd861ae
commit 8052066ab0
18 changed files with 423 additions and 41 deletions

View file

@ -90,13 +90,13 @@ namespace System
static function void(StringView str) OutString = => OutString_Simple; static function void(StringView str) OutString = => OutString_Simple;
[CLink, CallingConvention(.Cdecl)] public static extern void PutChar(char8 c);
static extern void putchar(char8 c); public static extern void ReopenHandles();
static void OutString_Simple(StringView str) static void OutString_Simple(StringView str)
{ {
for (var c in str.RawChars) for (var c in str.RawChars)
putchar(c); PutChar(c);
} }
static void OutString_Ex(StringView str) static void OutString_Ex(StringView str)

View file

@ -1496,6 +1496,9 @@ namespace System
[CLink, CallingConvention(.Stdcall)] [CLink, CallingConvention(.Stdcall)]
public static extern IntBool GetExitCodeThread(Handle process, out int32 exitCode); 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)] [CLink, CallingConvention(.Stdcall)]
public static extern int32 ResumeThread(Handle thread); public static extern int32 ResumeThread(Handle thread);

View file

@ -181,6 +181,13 @@ namespace bf
Beefy::String GetTypeName(); Beefy::String GetTypeName();
}; };
class Console
{
public:
BFRT_EXPORT static void PutChar(char c);
BFRT_EXPORT static void ReopenHandles();
};
class Exception : public Object class Exception : public Object
{ {

View file

@ -292,6 +292,26 @@ static void NTAPI TlsFreeFunc(void* ptr)
gBfRtCallbacks.Thread_Exiting(); 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) void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
{ {
BfpSystemInitFlags sysInitFlags = BfpSystemInitFlag_InstallCrashCatcher; BfpSystemInitFlags sysInitFlags = BfpSystemInitFlag_InstallCrashCatcher;

View file

@ -12,14 +12,20 @@ class Program
BeefConConsoleProvider.Pipe mPipe ~ delete _; BeefConConsoleProvider.Pipe mPipe ~ delete _;
WinNativeConsoleProvider mProvider ~ delete _; WinNativeConsoleProvider mProvider ~ delete _;
int32 mPid; int32 mPid;
int32 mAttachedPid;
Windows.ProcessHandle mAttachedProcess;
String mAttachedName = new .() ~ delete _;
int32 mConid; int32 mConid;
String mExecStr = new .() ~ delete _; String mExecStr = new .() ~ delete _;
SpawnedProcess mSpawnedProcess ~ delete _; SpawnedProcess mSpawnedProcess ~ delete _;
public ~this() public ~this()
{ {
mSpawnedProcess.Kill(); if (mSpawnedProcess != null)
mSpawnedProcess.WaitFor(); {
mSpawnedProcess.Kill();
mSpawnedProcess.WaitFor();
}
} }
static mixin GET<T>(var ptr) static mixin GET<T>(var ptr)
@ -105,6 +111,16 @@ class Program
case .Update: case .Update:
bool paused = GET!<bool>(ptr); bool paused = GET!<bool>(ptr);
mProvider.Update(paused); 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: default:
} }
case .Err(let err): 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() public void Run()
{ {
mPipe = new .(); mPipe = new .();
mPipe.Listen(mPid, mConid); mPipe.Listen(mPid, mConid);
mProvider = new .(); mProvider = new .();
//mProvider.mHideNativeConsole = false; mProvider.mHideNativeConsole = !mExecStr.IsEmpty;
mProvider.Attach(); mProvider.Attach();
Console.ReopenHandles();
ProcessStartInfo procInfo = scope ProcessStartInfo(); if (!mExecStr.IsEmpty)
procInfo.UseShellExecute = false; {
procInfo.SetFileName(mExecStr); ProcessStartInfo procInfo = scope ProcessStartInfo();
procInfo.UseShellExecute = false;
procInfo.SetFileName(mExecStr);
mSpawnedProcess = new SpawnedProcess(); mSpawnedProcess = new SpawnedProcess();
if (mSpawnedProcess.Start(procInfo) case .Err) if (mSpawnedProcess.Start(procInfo) case .Err)
return; 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) while (true)
{ {
@ -146,25 +251,31 @@ class Program
if (!mPipe.mConnected) if (!mPipe.mConnected)
Thread.Sleep(20); Thread.Sleep(20);
if (mSpawnedProcess.WaitFor(0))
return;
} }
} }*/
public static int Main(String[] args) 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; return 1;
} }
Program pg = scope .(); Program pg = scope .();
pg.mPid = int32.Parse(args[0]); if (args.Count >= 3)
pg.mConid = int32.Parse(args[1]); {
pg.mExecStr.Set(args[2]); pg.mPid = int32.Parse(args[0]);
pg.Run(); 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; return 0;
} }

View file

@ -1500,7 +1500,7 @@ BFP_EXPORT void BFP_CALLTYPE BfpProcess_GetProcessName(BfpProcess* process, char
OUTRESULT(BfpProcessResult_UnknownError); OUTRESULT(BfpProcessResult_UnknownError);
return; return;
} }
WCHAR wName[MAX_PATH]; WCHAR wName[MAX_PATH] = { 0 };
::GetModuleFileNameExW(hProc, NULL, wName, MAX_PATH); ::GetModuleFileNameExW(hProc, NULL, wName, MAX_PATH);
::CloseHandle(hProc); ::CloseHandle(hProc);
String name = UTF8Encode(wName); String name = UTF8Encode(wName);

View file

@ -270,7 +270,7 @@ namespace IDE.Debugger
static extern char8* Debugger_GetCollectionContinuation(char8* continuationData, int32 callStackIdx, int32 count); static extern char8* Debugger_GetCollectionContinuation(char8* continuationData, int32 callStackIdx, int32 count);
[CallingConvention(.Stdcall),CLink] [CallingConvention(.Stdcall),CLink]
static extern void Debugger_ForegroundTarget(); static extern void Debugger_ForegroundTarget(int32 altProcessId);
[CallingConvention(.Stdcall),CLink] [CallingConvention(.Stdcall),CLink]
static extern void CallStack_Update(); static extern void CallStack_Update();
@ -314,6 +314,9 @@ namespace IDE.Debugger
[CallingConvention(.Stdcall),CLink] [CallingConvention(.Stdcall),CLink]
static extern char8* Debugger_GetProcessInfo(); static extern char8* Debugger_GetProcessInfo();
[CallingConvention(.Stdcall),CLink]
static extern int32 Debugger_GetProcessId();
[CallingConvention(.Stdcall),CLink] [CallingConvention(.Stdcall),CLink]
static extern char8* Debugger_GetThreadInfo(); static extern char8* Debugger_GetThreadInfo();
@ -912,9 +915,9 @@ namespace IDE.Debugger
outVal.Append(result); outVal.Append(result);
} }
public void ForegroundTarget() public void ForegroundTarget(int32 altProcessId)
{ {
Debugger_ForegroundTarget(); Debugger_ForegroundTarget(altProcessId);
} }
public void UpdateCallStack() public void UpdateCallStack()
@ -1079,6 +1082,13 @@ namespace IDE.Debugger
outProcessInfo.Append(strPtr); outProcessInfo.Append(strPtr);
} }
public int32 GetProcessId()
{
if (!mIsRunning)
return 0;
return Debugger_GetProcessId();
}
public void GetThreadInfo(String outThreadInfo) public void GetThreadInfo(String outThreadInfo)
{ {
if (!mIsRunning) if (!mIsRunning)

View file

@ -426,8 +426,15 @@ namespace IDE
public int mSampleRate; public int mSampleRate;
} }
class OpenDebugConsoleCmd : ExecutionCmd
{
}
class StartDebugCmd : ExecutionCmd class StartDebugCmd : ExecutionCmd
{ {
public bool mConnectedToConsole;
public int32 mConsoleProcessId;
public bool mWasCompiled; public bool mWasCompiled;
public bool mHotCompileEnabled; 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; defer delete next;
mExecutionQueue.RemoveAt(0); mExecutionQueue.RemoveAt(0);
@ -9336,6 +9410,19 @@ namespace IDE
} }
else else
OutputLine("Failed to start debugger"); 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) else if (next is ExecutionQueueCmd)
@ -13781,7 +13868,12 @@ namespace IDE
if (mForegroundTargetCountdown > 0) if (mForegroundTargetCountdown > 0)
{ {
if ((--mForegroundTargetCountdown == 0) && (mDebugger.mIsRunning)) 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)) if ((mDebugger != null) && (mExecutionPaused) && (mDebugger.mIsRunning))
@ -13845,6 +13937,33 @@ namespace IDE
DeleteAndNullify!(mLaunchData); DeleteAndNullify!(mLaunchData);
mErrorsPanel?.UpdateAlways(); 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) public void ShowPassOutput(BfPassInstance bfPassInstance)

View file

@ -1122,6 +1122,7 @@ namespace IDE
public String mWindowsTerminal = new .("Powershell") ~ delete _; public String mWindowsTerminal = new .("Powershell") ~ delete _;
public ConsoleKind mDebugConsoleKind; public ConsoleKind mDebugConsoleKind;
public bool mAlwaysEnableConsole; public bool mAlwaysEnableConsole;
public bool mKeepNativeConsoleOpen;
public String mEmscriptenPath = new .() ~ delete _; public String mEmscriptenPath = new .() ~ delete _;
public bool mEnableDevMode; public bool mEnableDevMode;
public TutorialsFinished mTutorialsFinished = .(); public TutorialsFinished mTutorialsFinished = .();
@ -1184,6 +1185,7 @@ namespace IDE
sd.Add("WindowsTerminal", mWindowsTerminal); sd.Add("WindowsTerminal", mWindowsTerminal);
sd.Add("DebugConsole", mDebugConsoleKind); sd.Add("DebugConsole", mDebugConsoleKind);
sd.Add("AlwaysEnableConsole", mAlwaysEnableConsole); sd.Add("AlwaysEnableConsole", mAlwaysEnableConsole);
sd.Add("KeepNativeConsoleOpen", mKeepNativeConsoleOpen);
} }
using (sd.CreateObject("Wasm")) using (sd.CreateObject("Wasm"))
sd.Add("EmscriptenPath", mEmscriptenPath); sd.Add("EmscriptenPath", mEmscriptenPath);
@ -1279,6 +1281,7 @@ namespace IDE
sd.Get("WindowsTerminal", mWindowsTerminal); sd.Get("WindowsTerminal", mWindowsTerminal);
mDebugConsoleKind = sd.GetEnum<ConsoleKind>("DebugConsole", .Native); mDebugConsoleKind = sd.GetEnum<ConsoleKind>("DebugConsole", .Native);
mAlwaysEnableConsole = sd.GetBool("AlwaysEnableConsole"); mAlwaysEnableConsole = sd.GetBool("AlwaysEnableConsole");
mKeepNativeConsoleOpen = sd.GetBool("KeepNativeConsoleOpen");
} }
using (sd.Open("Wasm")) using (sd.Open("Wasm"))
sd.Get("EmscriptenPath", mEmscriptenPath); sd.Get("EmscriptenPath", mEmscriptenPath);

View file

@ -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 ConsoleProvider mConsoleProvider ~ delete _;
public DarkCheckBox mMousePassthroughCB; public DarkCheckBox mMousePassthroughCB;
public DarkCheckBox mPauseCB; public DarkCheckBox mPauseCB;
@ -290,6 +297,7 @@ class ConsolePanel : Panel
public int32 mCellHeight; public int32 mCellHeight;
public (Position start, Position end)? mSelection; public (Position start, Position end)? mSelection;
public Position? mClickPos; public Position? mClickPos;
public BeefConAttachState mBeefConAttachState;
public bool Paused public bool Paused
{ {
@ -781,6 +789,14 @@ class ConsolePanel : Panel
public void Detach() public void Detach()
{ {
if (mBeefConAttachState case .Attached)
{
#if BF_PLATFORM_WINDOWS
WinNativeConsoleProvider.FreeConsole();
#endif
mBeefConAttachState = .None;
}
if (!mConsoleProvider.Attached) if (!mConsoleProvider.Attached)
return; return;
mConsoleProvider.Detach(); mConsoleProvider.Detach();

View file

@ -181,6 +181,7 @@ namespace IDE.ui
AddPropertiesItem(category, "Windows Terminal", "mWindowsTerminal"); AddPropertiesItem(category, "Windows Terminal", "mWindowsTerminal");
AddPropertiesItem(category, "Debug Console", "mDebugConsoleKind"); AddPropertiesItem(category, "Debug Console", "mDebugConsoleKind");
AddPropertiesItem(category, "Always Enable Console", "mAlwaysEnableConsole"); AddPropertiesItem(category, "Always Enable Console", "mAlwaysEnableConsole");
AddPropertiesItem(category, "Keep Native Console Open", "mKeepNativeConsoleOpen");
category.Open(true, true); category.Open(true, true);
} }

View file

@ -250,10 +250,13 @@ class WinNativeConsoleProvider : ConsoleProvider
#if BF_PLATFORM_WINDOWS #if BF_PLATFORM_WINDOWS
[CLink, CallingConvention(.Stdcall)] [CLink, CallingConvention(.Stdcall)]
public static extern void AllocConsole(); public static extern Windows.IntBool AllocConsole();
[CLink, CallingConvention(.Stdcall)] [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)] [CLink, CallingConvention(.Stdcall)]
public static extern void FreeConsole(); public static extern void FreeConsole();
@ -290,6 +293,15 @@ class WinNativeConsoleProvider : ConsoleProvider
[CLink] [CLink]
public static extern Windows.IntBool ReadConsoleInputW(Windows.Handle handle, INPUT_RECORD* eventsPtr, int32 eventCount, out int32 numEventsRead); 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 #endif
ScreenInfo mScreenInfo ~ delete _; ScreenInfo mScreenInfo ~ delete _;
@ -789,6 +801,58 @@ class WinNativeConsoleProvider : ConsoleProvider
{ {
return (mScreenInfo != null) ? mScreenInfo.mColorTable[i] : 0xFF000000; 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 class BeefConConsoleProvider : ConsoleProvider
@ -807,7 +871,8 @@ class BeefConConsoleProvider : ConsoleProvider
MouseUp, MouseUp,
MouseWheel, MouseWheel,
ScrollTo, ScrollTo,
Update Update,
Attached
} }
public class Pipe public class Pipe

View file

@ -409,7 +409,7 @@ void CeDebugger::ContinueDebugEvent()
mCeMachine->mDebugEvent.Set(); mCeMachine->mDebugEvent.Set();
} }
void CeDebugger::ForegroundTarget() void CeDebugger::ForegroundTarget(int altProcessId)
{ {
} }
@ -4361,6 +4361,11 @@ String CeDebugger::GetProcessInfo()
return String(); return String();
} }
int CeDebugger::GetProcessId()
{
return 0;
}
DebugVisualizerEntry* CeDebugger::FindVisualizerForType(BfType* dbgType, Array<String>* wildcardCaptures) DebugVisualizerEntry* CeDebugger::FindVisualizerForType(BfType* dbgType, Array<String>* wildcardCaptures)
{ {
auto ceModule = mCeMachine->mCeModule; auto ceModule = mCeMachine->mCeModule;

View file

@ -324,7 +324,7 @@ public:
virtual String GetDbgAllocInfo() override; virtual String GetDbgAllocInfo() override;
virtual void Update() override; virtual void Update() override;
virtual void ContinueDebugEvent() 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* CreateBreakpoint(const StringImpl& fileName, int lineNum, int wantColumn, int instrOffset) override;
virtual Breakpoint* CreateMemoryBreakpoint(intptr addr, int byteCount) override; virtual Breakpoint* CreateMemoryBreakpoint(intptr addr, int byteCount) override;
virtual Breakpoint* CreateSymbolBreakpoint(const StringImpl& symbolName) override; virtual Breakpoint* CreateSymbolBreakpoint(const StringImpl& symbolName) override;
@ -359,6 +359,7 @@ public:
virtual String GetAutoLocals(int callStackIdx, bool showRegs) override; virtual String GetAutoLocals(int callStackIdx, bool showRegs) override;
virtual String CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx) override; virtual String CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx) override;
virtual String GetProcessInfo() override; virtual String GetProcessInfo() override;
virtual int GetProcessId() override;
virtual String GetThreadInfo() override; virtual String GetThreadInfo() override;
virtual void SetActiveThread(int threadId) override; virtual void SetActiveThread(int threadId) override;
virtual int GetActiveThread() override; virtual int GetActiveThread() override;

View file

@ -1363,9 +1363,9 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetCollectionContinuation(const char*
return outString.c_str(); 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); //BOOL worked = EnumThreadWindows(gDebugger->mProcessInfo.dwThreadId, WdEnumWindowsProc, 0);
//BF_ASSERT(worked); //BF_ASSERT(worked);
@ -1378,6 +1378,11 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetProcessInfo()
return outString.c_str(); return outString.c_str();
} }
BF_EXPORT int BF_CALLTYPE Debugger_GetProcessId()
{
return gDebugger->GetProcessId();
}
BF_EXPORT const char* BF_CALLTYPE Debugger_GetThreadInfo() BF_EXPORT const char* BF_CALLTYPE Debugger_GetThreadInfo()
{ {
String& outString = *gTLStrReturn.Get(); String& outString = *gTLStrReturn.Get();

View file

@ -285,7 +285,7 @@ public:
virtual String GetDbgAllocInfo() = 0; virtual String GetDbgAllocInfo() = 0;
virtual void Update() = 0; virtual void Update() = 0;
virtual void ContinueDebugEvent() = 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* CreateBreakpoint(const StringImpl& fileName, int lineNum, int wantColumn, int instrOffset) = 0;
virtual Breakpoint* CreateMemoryBreakpoint(intptr addr, int byteCount) = 0; virtual Breakpoint* CreateMemoryBreakpoint(intptr addr, int byteCount) = 0;
virtual Breakpoint* CreateSymbolBreakpoint(const StringImpl& symbolName) = 0; virtual Breakpoint* CreateSymbolBreakpoint(const StringImpl& symbolName) = 0;
@ -320,6 +320,7 @@ public:
virtual String GetAutoLocals(int callStackIdx, bool showRegs) = 0; virtual String GetAutoLocals(int callStackIdx, bool showRegs) = 0;
virtual String CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx) = 0; virtual String CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx) = 0;
virtual String GetProcessInfo() = 0; virtual String GetProcessInfo() = 0;
virtual int GetProcessId() = 0;
virtual String GetThreadInfo() = 0; virtual String GetThreadInfo() = 0;
virtual void SetActiveThread(int threadId) = 0; virtual void SetActiveThread(int threadId) = 0;
virtual int GetActiveThread() = 0; virtual int GetActiveThread() = 0;

View file

@ -3055,6 +3055,8 @@ void WinDebugger::ContinueDebugEvent()
static BOOL CALLBACK WdEnumWindowsProc(HWND hwnd, LPARAM lParam) static BOOL CALLBACK WdEnumWindowsProc(HWND hwnd, LPARAM lParam)
{ {
int wantProcessId = lParam;
HWND owner = GetWindow(hwnd, GW_OWNER); HWND owner = GetWindow(hwnd, GW_OWNER);
if (!IsWindowVisible(hwnd)) if (!IsWindowVisible(hwnd))
return TRUE; return TRUE;
@ -3062,7 +3064,7 @@ static BOOL CALLBACK WdEnumWindowsProc(HWND hwnd, LPARAM lParam)
DWORD processId = 0; DWORD processId = 0;
DWORD threadId = GetWindowThreadProcessId(hwnd, &processId); DWORD threadId = GetWindowThreadProcessId(hwnd, &processId);
if (processId != ((WinDebugger*)gDebugger)->mProcessInfo.dwProcessId) if (processId != wantProcessId)
return TRUE; return TRUE;
while (true) while (true)
@ -3080,8 +3082,12 @@ static BOOL CALLBACK WdEnumWindowsProc(HWND hwnd, LPARAM lParam)
return TRUE; return TRUE;
} }
void WinDebugger::ForegroundTarget() void WinDebugger::ForegroundTarget(int altProcessId)
{ {
int wantProcessId = altProcessId;
if (wantProcessId == 0)
wantProcessId = ((WinDebugger*)gDebugger)->mProcessInfo.dwProcessId;
HWND hwnd = ::GetForegroundWindow(); HWND hwnd = ::GetForegroundWindow();
if (hwnd != INVALID_HANDLE_VALUE) if (hwnd != INVALID_HANDLE_VALUE)
{ {
@ -3091,7 +3097,7 @@ void WinDebugger::ForegroundTarget()
return; // Already good return; // Already good
} }
EnumWindows(WdEnumWindowsProc, 0); EnumWindows(WdEnumWindowsProc, wantProcessId);
} }
static int gFindLineDataAt = 0; static int gFindLineDataAt = 0;
@ -10977,6 +10983,14 @@ String WinDebugger::GetProcessInfo()
return retStr; return retStr;
} }
int WinDebugger::GetProcessId()
{
AutoCrit autoCrit(mDebugManager->mCritSect);
if (!mThreadList.IsEmpty())
return mThreadList[0]->mProcessId;
return mDbgProcessId;
}
String WinDebugger::GetThreadInfo() String WinDebugger::GetThreadInfo()
{ {
AutoCrit autoCrit(mDebugManager->mCritSect); AutoCrit autoCrit(mDebugManager->mCritSect);

View file

@ -598,7 +598,7 @@ public:
virtual String GetDbgAllocInfo() override; virtual String GetDbgAllocInfo() override;
virtual void Update() override; virtual void Update() override;
virtual void ContinueDebugEvent() 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* CreateBreakpoint(const StringImpl& fileName, int lineNum, int wantColumn, int instrOffset) override;
virtual Breakpoint* CreateMemoryBreakpoint(intptr addr, int byteCount) override; virtual Breakpoint* CreateMemoryBreakpoint(intptr addr, int byteCount) override;
virtual Breakpoint* CreateSymbolBreakpoint(const StringImpl& symbolName) override; virtual Breakpoint* CreateSymbolBreakpoint(const StringImpl& symbolName) override;
@ -630,6 +630,7 @@ public:
virtual String GetAutoLocals(int callStackIdx, bool showRegs) override; virtual String GetAutoLocals(int callStackIdx, bool showRegs) override;
virtual String CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx) override; virtual String CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx) override;
virtual String GetProcessInfo() override; virtual String GetProcessInfo() override;
virtual int GetProcessId() override;
virtual String GetThreadInfo() override; virtual String GetThreadInfo() override;
virtual void SetActiveThread(int threadId) override; virtual void SetActiveThread(int threadId) override;
virtual int GetActiveThread() override; virtual int GetActiveThread() override;