Library Manager now complete just one last option needed, debugger will now throw an event when the process were attached to dies & testing for IPC so we dont try to load the helper multiple times.

This commit is contained in:
Greg
2023-01-07 20:50:46 -07:00
parent 8739686698
commit 4f495f54ba
13 changed files with 475 additions and 66 deletions
+1
View File
@@ -5,6 +5,7 @@
enum GeneralIPCCommands
{
GIPC_HELLO,
GIPC_LIB_LIST,
GIPC_LIB_LOAD,
GIPC_LIB_UNLOAD,
+93 -15
View File
@@ -90,18 +90,89 @@ bool Debug::TryDetach(int pid)
int res = ptrace(PT_DETACH, pid, nullptr, 0);
if (res != 0)
{
// Check if proc is dead anyway and just detach.
klog("DetachProcess(): ptrace(PT_DETACH) failed with error %llX\n", res);
return false;
}
// TODO: Kill the watching thread and Remove any Watchpoints / Breakpoints now.
// Reset vars.
IsDebugging = false;
CurrentPID = -1;
// Wait for the current proc thread to die.
scePthreadJoin(*ProcMonitorThreadHandle, nullptr);
return true;
}
void* Debug::ProcessMonotorThread()
{
while (IsDebugging && CurrentPID != -1)
{
std::vector<kinfo_proc> procList;
GetProcessList(procList);
int currentPID = CurrentPID;
if (std::find_if(procList.begin(), procList.end(), [&currentPID](const kinfo_proc& arg) {
return arg.pid == currentPID;
}) == procList.end())
{
klog("Proc %d has died.\n", CurrentPID);
// Aquire lock.
scePthreadMutexLock(&DebugMutex);
// Reset vars.
IsDebugging = false;
CurrentPID = -1;
// Send attach event to host.
Events::SendEvent(Events::EVENT_DIE, CurrentPID);
// Let the process die.
ptrace(PT_CONTINUE, CurrentPID, (void*)1, SIGKILL);
// release the lock.
scePthreadMutexUnlock(&DebugMutex);
goto Thread_Exit;
}
int status;
auto debuggiePid = wait4(CurrentPID, &status, WNOHANG, nullptr);
if (debuggiePid == CurrentPID)
{
int signal = WSTOPSIG(status);
klog("Process %d has recieved the signal %d\n", CurrentPID, signal);
switch (signal)
{
case SIGSTOP:
klog("SIGSTOP\n");
break;
}
}
sceKernelSleep(1);
}
Thread_Exit:
klog("Client Thread Exiting!\n");
// TODO: Remove any Watchpoints / Breakpoints now.
// Unless the process is dying maybe?
// Kill our thread and exit.
scePthreadExit(NULL);
return nullptr;
}
void* Debug::ProcessMonotorThreadHelper(void* tdParam)
{
return ((Debug*)tdParam)->ProcessMonotorThread();
}
void Debug::Attach(OrbisNetId Sock)
{
auto pid = RecieveInt(Sock);
@@ -156,6 +227,9 @@ void Debug::Attach(OrbisNetId Sock)
IsDebugging = true;
CurrentPID = pid;
// Create thread to monitor the state of the running process.
scePthreadCreate(&ProcMonitorThreadHandle, NULL, &ProcessMonotorThreadHelper, this, "Process Monitor Thread");
// release the lock.
scePthreadMutexUnlock(&DebugMutex);
@@ -166,23 +240,27 @@ void Debug::Attach(OrbisNetId Sock)
SendStatus(Sock, 1);
if (strcmp(processName, "SceShellCore"))
// Check the satus of the general helper.
if (!GeneralIPC::TestConnection(pid))
{
// Get app info.
OrbisAppInfo appInfo;
sceKernelGetAppInfo(pid, &appInfo);
if (strcmp(processName, "SceShellCore"))
{
// Get app info.
OrbisAppInfo appInfo;
sceKernelGetAppInfo(pid, &appInfo);
// Get sandbox path.
char sandBoxPath[PATH_MAX];
snprintf(sandBoxPath, sizeof(sandBoxPath), "/mnt/sandbox/%s_000/data", appInfo.TitleId);
// Get sandbox path.
char sandBoxPath[PATH_MAX];
snprintf(sandBoxPath, sizeof(sandBoxPath), "/mnt/sandbox/%s_000/data", appInfo.TitleId);
// Mount data into sandbox
LinkDir("/data/", sandBoxPath);
// Mount data into sandbox
LinkDir("/data/", sandBoxPath);
}
// Load the helper library.
int handle = sys_sdk_proc_prx_load(processName, HelperPrxPath);
klog("Helper handle = %llX\n", handle);
}
// Load the helper library.
int handle = sys_sdk_proc_prx_load(processName, HelperPrxPath);
klog("Helper handle = %llX\n", handle);
}
void Debug::Detach(OrbisNetId Sock)
+3
View File
@@ -4,6 +4,7 @@ class Debug
{
public:
OrbisPthreadMutex DebugMutex;
OrbisPthread* ProcMonitorThreadHandle;
bool IsDebugging;
int CurrentPID;
@@ -13,6 +14,8 @@ public:
private:
bool TryDetach(int pid);
void* ProcessMonotorThread();
static void* ProcessMonotorThreadHelper(void* tdParam);
void Attach(OrbisNetId Sock);
void Detach(OrbisNetId Sock);
+96 -2
View File
@@ -42,6 +42,43 @@ bool GeneralIPC::SendCommand(OrbisNetId Sock, int Command)
return Status == GIPC_OK;
}
bool GeneralIPC::TestConnection(int pid)
{
// Open a new local socket connection for the process.
auto sock = Connect(pid);
if (!sock)
{
klog("[GeneralIPC] Failed to connect to socket.\n");
return false;
}
// Send the command.
if (!SendCommand(sock, GIPC_HELLO))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to send command.\n");
return false;
}
// Get the library count.
int status = 0;
if (!Sockets::RecvInt(sock, &status))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to recv status.\n");
return false;
}
// Close the socket.
sceNetSocketClose(sock);
return status == GIPC_OK;
}
bool GeneralIPC::GetLibraryList(int pid, std::vector<LibraryPacket>& Libraries)
{
// Open a new local socket connection for the process.
@@ -55,6 +92,9 @@ bool GeneralIPC::GetLibraryList(int pid, std::vector<LibraryPacket>& Libraries)
// Send the command.
if (!SendCommand(sock, GIPC_LIB_LIST))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to send command.\n");
return false;
}
@@ -63,6 +103,9 @@ bool GeneralIPC::GetLibraryList(int pid, std::vector<LibraryPacket>& Libraries)
int LibraryCount = 0;
if (!Sockets::RecvInt(sock, &LibraryCount))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to recv library count.\n");
return false;
}
@@ -72,10 +115,16 @@ bool GeneralIPC::GetLibraryList(int pid, std::vector<LibraryPacket>& Libraries)
if (!Sockets::RecvLargeData(sock, (unsigned char*)Libraries.data(), LibraryCount * sizeof(LibPacket)))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to recv library data.\n");
return false;
}
// Close the socket.
sceNetSocketClose(sock);
return true;
}
@@ -92,6 +141,9 @@ bool GeneralIPC::LoadLibrary(int pid, const char* Path, int* HandleOut)
// Send the command.
if (!SendCommand(sock, GIPC_LIB_LOAD))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to send command.\n");
return false;
}
@@ -106,6 +158,9 @@ bool GeneralIPC::LoadLibrary(int pid, const char* Path, int* HandleOut)
// Send the packet.
if (sceNetSend(sock, Packet, sizeof(LibPacket), 0) < 0)
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to send LibPacket.\n");
// Restore the jail.
@@ -117,6 +172,9 @@ bool GeneralIPC::LoadLibrary(int pid, const char* Path, int* HandleOut)
// Recieve the result.
if (!Sockets::RecvInt(sock, HandleOut))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to recv handle.\n");
// Restore the jail.
@@ -128,6 +186,9 @@ bool GeneralIPC::LoadLibrary(int pid, const char* Path, int* HandleOut)
// Check to see if it was loaded successfully.
if (*HandleOut <= 0)
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to load PRX '%s' (0x%llX).\n", *HandleOut);
// Restore the jail.
@@ -139,6 +200,9 @@ bool GeneralIPC::LoadLibrary(int pid, const char* Path, int* HandleOut)
// Restore the jail.
Jail(pid);
// Close the socket.
sceNetSocketClose(sock);
return true;
}
@@ -155,6 +219,9 @@ bool GeneralIPC::UnLoadLibrary(int pid, int Handle)
// Send the command.
if (!SendCommand(sock, GIPC_LIB_UNLOAD))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to send command.\n");
return false;
}
@@ -163,6 +230,9 @@ bool GeneralIPC::UnLoadLibrary(int pid, int Handle)
int result = 0;
if (!Sockets::RecvInt(sock, &result))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to recv result.\n");
return false;
}
@@ -170,10 +240,16 @@ bool GeneralIPC::UnLoadLibrary(int pid, int Handle)
// Check to see if it was unloaded successfully.
if (result != 0)
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to un load PRX '%s' (0x%llX).\n", result);
return false;
}
// Close the socket.
sceNetSocketClose(sock);
return true;
}
@@ -190,6 +266,9 @@ bool GeneralIPC::Jailbreak(int pid)
// Send the command.
if (!SendCommand(sock, GIPC_JAILBREAK))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to send command.\n");
return false;
}
@@ -198,11 +277,17 @@ bool GeneralIPC::Jailbreak(int pid)
int result = 0;
if (!Sockets::RecvInt(sock, &result))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to recv result.\n");
return false;
}
return result == 1;
// Close the socket.
sceNetSocketClose(sock);
return result == GIPC_OK;
}
bool GeneralIPC::Jail(int pid)
@@ -218,6 +303,9 @@ bool GeneralIPC::Jail(int pid)
// Send the command.
if (!SendCommand(sock, GIPC_JAIL))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to send command.\n");
return false;
}
@@ -226,9 +314,15 @@ bool GeneralIPC::Jail(int pid)
int result = 0;
if (!Sockets::RecvInt(sock, &result))
{
// Close the socket.
sceNetSocketClose(sock);
klog("[GeneralIPC] Failed to recv result.\n");
return false;
}
return result == 1;
// Close the socket.
sceNetSocketClose(sock);
return result == GIPC_OK;
}
+1
View File
@@ -8,6 +8,7 @@ private:
static bool SendCommand(OrbisNetId Sock, int Command);
public:
static bool TestConnection(int pid);
static bool GetLibraryList(int pid, std::vector<LibraryPacket>& Libraries);
static bool LoadLibrary(int pid, const char* Path, int* HandleOut);
static bool UnLoadLibrary(int pid, int Handle);
+1 -3
View File
@@ -127,10 +127,8 @@ void* SocketListener::ListenThread(void* tdParam)
return ((SocketListener*)tdParam)->DoWork();
}
SocketListener::SocketListener(void(*ClientCallBack)(void* tdParam, OrbisNetId Sock, OrbisNetInAddr sin_addr), void* tdParam, unsigned short Port)
{
klog("Socket Listener.\n");
this->ClientCallBack = ClientCallBack;
this->tdParam = tdParam;
this->ServerRunning = true;
@@ -145,7 +143,7 @@ SocketListener::~SocketListener()
klog("~Socket Listener.\n");
this->ServerRunning = false;
while (!this->ThreadCleanedUp) { sceKernelUsleep(10); }
scePthreadJoin(*ListenThreadHandle, nullptr);
klog("Destruction sucessful.\n");
}
+11 -11
View File
@@ -1,11 +1,11 @@
#pragma once
#define ORBISLIB_MAJOR 3
#define ORBISLIB_MINOR 0
#define ORBISLIB_BUILDVERSION 951
#define stringify(a) stringify_(a)
#define stringify_(a) #a
#if defined(_DEBUG)
#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Dev Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__)
#else
#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__)
#endif
#pragma once
#define ORBISLIB_MAJOR 3
#define ORBISLIB_MINOR 0
#define ORBISLIB_BUILDVERSION 984
#define stringify(a) stringify_(a)
#define stringify_(a) #a
#if defined(_DEBUG)
#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Dev Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__)
#else
#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__)
#endif
+8
View File
@@ -21,8 +21,16 @@ void exiting()
}
// Signal handler function
void signal_handler(int signum) {
klog("Signal %d\n", signum);
}
int main()
{
signal(17, signal_handler);
signal(SIGTERM, signal_handler);
// Jailbreak our current process.
if (!Jailbreak())
{
@@ -83,6 +83,12 @@ void ListenerClientThread(void* tdParam, OrbisNetId Sock)
klog("Invalid Command enum %i\n", Command);
break;
case GIPC_HELLO:
Sockets::SendInt(Sock, GIPC_OK);
break;
case GIPC_LIB_LIST:
SendLibraryList(Sock); // Really Only needed for the path.
break;
@@ -48,8 +48,10 @@
<StackPanel HorizontalAlignment="Right"
Margin="6">
<simpleControls:SimpleTextField FieldName="SPRX Path"
FieldText="/data/something.sprx"
<simpleControls:SimpleTextField Name="SPRXPath"
FieldName="SPRX Path"
FieldText=""
IsReadOnly="False"
VerticalContentAlignment="Center"
Width="180"/>
@@ -65,19 +67,25 @@
</Grid.ColumnDefinitions>
<simpleControls:SimpleButton Grid.Column="0"
Name="LoadPRX"
Content="Load"
Width="56"
Height="25"/>
Height="25"
Click="LoadPRX_Click"/>
<simpleControls:SimpleButton Grid.Column="2"
Name="UnloadPRX"
Content="Unload"
Width="56"
Height="25"/>
Height="25"
Click="UnloadPRX_Click"/>
<simpleControls:SimpleButton Grid.Column="4"
Name="ReloadPRX"
Content="Reload"
Width="56"
Height="25"/>
Height="25"
Click="ReloadPRX_Click"/>
</Grid>
@@ -87,8 +95,9 @@
<StackPanel HorizontalAlignment="Right"
Margin="0 6 6 6">
<simpleControls:SimpleTextField FieldName="Currently Debugging"
FieldText="SceShellUI.ELF (75)"
<simpleControls:SimpleTextField Name="CurrentDebuggingProccess"
FieldName="Currently Debugging"
FieldText="N/A"
VerticalContentAlignment="Center"
Width="180"/>
@@ -127,13 +136,14 @@
ImageMargin="2"
Click="DetachProcess_Click"/>
<controls:ImageButton x:Name="Send"
<controls:ImageButton x:Name="LoadSomething"
Grid.Column="4"
Width="25"
Height="25"
ToolTip="Browse for something to load from local machine"
ImageSource="/OrbisLibraryManager;component/Images/Send.png"
ImageMargin="5"/>
ImageMargin="5"
Click="LoadSomething_Click"/>
<controls:ImageButton x:Name="KillProcess"
Grid.Column="6"
@@ -141,7 +151,8 @@
Height="25"
ToolTip="Kills the currently attached process"
ImageSource="/OrbisLibraryManager;component/Images/KillProcess.png"
ImageMargin="1"/>
ImageMargin="1"
Click="KillProcess_Click"/>
<controls:ImageButton x:Name="RestartTarget"
Grid.Column="8"
@@ -149,7 +160,8 @@
Height="25"
ToolTip="Restart the Target"
ImageSource="/OrbisLibraryManager;component/Images/Restart.png"
ImageMargin="0"/>
ImageMargin="0"
Click="RestartTarget_Click"/>
<controls:ImageButton x:Name="ShutdownTarget"
Grid.Column="10"
@@ -157,7 +169,8 @@
Height="25"
ToolTip="Shutdown the Target"
ImageSource="/OrbisLibraryManager;component/Images/Shutdown.png"
ImageMargin="0"/>
ImageMargin="0"
Click="ShutdownTarget_Click"/>
</Grid>
@@ -187,7 +200,10 @@
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Refresh" Click="Refresh_Click"/>
<MenuItem Name="RefreshLibraries" Header="Refresh Library List" Click="Refresh_Click"/>
<Separator/>
<MenuItem Name="UnloadLibrary" Header="Unload Library"/>
<MenuItem Name="ReloadLibrary" Header="Reload Library"/>
</ContextMenu>
</ListView.ContextMenu>
@@ -1,10 +1,13 @@
using OrbisLib2.Common.Dispatcher;
using OrbisLib2.Common.Database.Types;
using OrbisLib2.Common.Dispatcher;
using OrbisLib2.General;
using OrbisLib2.Targets;
using OrbisLib2.Dialog;
using SimpleUI.Controls;
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Linq;
using System.Threading;
namespace OrbisLibraryManager
{
@@ -20,22 +23,11 @@ namespace OrbisLibraryManager
Events.ProcAttach += Events_ProcAttach;
Events.ProcDetach += Events_ProcDetach;
}
Events.ProcDie += Events_ProcDie;
Events.TargetStateChanged += Events_TargetStateChanged;
private void Events_ProcDetach(object? sender, ProcDetachEvent e)
{
if(e.SendingTarget.IPAddress == TargetManager.SelectedTarget.IPAddress)
{
Console.WriteLine("ProcDetach");
}
}
private void Events_ProcAttach(object? sender, ProcAttachEvent e)
{
if (e.SendingTarget.IPAddress == TargetManager.SelectedTarget.IPAddress)
{
Console.WriteLine($"ProcAttach {e.NewProcessId}");
}
// Update State
Task.Run(() => EnableTargetOptions(TargetManager.SelectedTarget.Info.Status == TargetStatusType.APIAvailable));
}
private void RefreshLibraryList()
@@ -62,9 +54,191 @@ namespace OrbisLibraryManager
});
}
#region Events
private void EnableProgram(bool Attached)
{
if(Attached)
{
RefreshLibraryList();
}
else
{
LibraryList.ItemsSource = null;
}
LoadPRX.IsEnabled = Attached;
UnloadPRX.IsEnabled = Attached;
ReloadPRX.IsEnabled = Attached;
RefreshLibraries.IsEnabled = Attached;
UnloadLibrary.IsEnabled = Attached;
ReloadLibrary.IsEnabled = Attached;
DetachProcess.IsEnabled = Attached;
KillProcess.IsEnabled = Attached;
}
private void EnableTargetOptions(bool state)
{
Dispatcher.Invoke(() =>
{
AttachProcess.IsEnabled = state;
DetachProcess.IsEnabled = state;
LoadSomething.IsEnabled = state;
RestartTarget.IsEnabled = state;
ShutdownTarget.IsEnabled = state;
EnableProgram(TargetManager.SelectedTarget.Debug.IsDebugging);
});
}
private void Events_TargetStateChanged(object? sender, TargetStateChangedEvent e)
{
EnableTargetOptions(e.State == TargetStateChangedEvent.TargetState.APIAvailable);
}
private void Events_ProcDie(object? sender, ProcDieEvent e)
{
if (e.SendingTarget.IPAddress == TargetManager.SelectedTarget.IPAddress)
{
Dispatcher.Invoke(() =>
{
CurrentDebuggingProccess.FieldText = "N/A";
EnableProgram(false);
});
}
}
private void Events_ProcDetach(object? sender, ProcDetachEvent e)
{
if(e.SendingTarget.IPAddress == TargetManager.SelectedTarget.IPAddress)
{
Dispatcher.Invoke(() =>
{
CurrentDebuggingProccess.FieldText = "N/A";
EnableProgram(false);
});
}
}
private void Events_ProcAttach(object? sender, ProcAttachEvent e)
{
if (e.SendingTarget.IPAddress == TargetManager.SelectedTarget.IPAddress)
{
var processList = TargetManager.SelectedTarget.Process.GetList();
var proc = processList.Find(x => x.ProcessId == e.NewProcessId);
if(proc != null)
{
Dispatcher.Invoke(() =>
{
CurrentDebuggingProccess.FieldText = $"{proc.Name}({e.NewProcessId})";
EnableProgram(true);
});
}
}
}
#endregion
#region Context Menu
private void Refresh_Click(object sender, RoutedEventArgs e)
{
RefreshLibraryList();
}
private void UnloadLibrary_Click(object sender, RoutedEventArgs e)
{
var selectedLibrary = LibraryList.SelectedItems.Cast<LibraryInfo>().FirstOrDefault();
if(selectedLibrary != null)
{
Task.Run(() =>
{
TargetManager.SelectedTarget.Debug.UnloadLibrary((int)selectedLibrary.Handle);
Dispatcher.Invoke(() => RefreshLibraryList());
});
}
}
private void ReloadLibrary_Click(object sender, RoutedEventArgs e)
{
var selectedLibrary = LibraryList.SelectedItems.Cast<LibraryInfo>().FirstOrDefault();
if (selectedLibrary != null)
{
Task.Run(() =>
{
TargetManager.SelectedTarget.Debug.UnloadLibrary((int)selectedLibrary.Handle);
Thread.Sleep(2000);
TargetManager.SelectedTarget.Debug.LoadLibrary(selectedLibrary.Path);
Dispatcher.Invoke(() => RefreshLibraryList());
});
}
}
#endregion
#region Buttons
private void LoadPRX_Click(object sender, RoutedEventArgs e)
{
var libraryList = TargetManager.SelectedTarget.Debug.GetLibraries();
var library = libraryList.Find(x => x.Path == SPRXPath.FieldText);
if (library == null)
{
Task.Run(() =>
{
TargetManager.SelectedTarget.Debug.LoadLibrary(SPRXPath.FieldText);
Dispatcher.Invoke(() => RefreshLibraryList());
});
}
else
{
SimpleMessageBox.ShowError(Window.GetWindow(this), $"Could not load \"{SPRXPath}\" since it is already loaded.", "Error: Failed to load SPRX.");
}
}
private void UnloadPRX_Click(object sender, RoutedEventArgs e)
{
var libraryList = TargetManager.SelectedTarget.Debug.GetLibraries();
var library = libraryList.Find(x => x.Path == SPRXPath.FieldText);
if (library != null)
{
Task.Run(() =>
{
TargetManager.SelectedTarget.Debug.UnloadLibrary((int)library.Handle);
Dispatcher.Invoke(() => RefreshLibraryList());
});
}
else
{
SimpleMessageBox.ShowError(Window.GetWindow(this), $"Could not unload \"{SPRXPath}\" since it is not loaded.", "Error: Failed to unload SPRX.");
}
}
private void ReloadPRX_Click(object sender, RoutedEventArgs e)
{
var libraryList = TargetManager.SelectedTarget.Debug.GetLibraries();
var library = libraryList.Find(x => x.Path == SPRXPath.FieldText);
if (library != null)
{
Task.Run(() =>
{
TargetManager.SelectedTarget.Debug.UnloadLibrary((int)library.Handle);
Thread.Sleep(2000);
TargetManager.SelectedTarget.Debug.LoadLibrary(library.Path);
Dispatcher.Invoke(() => RefreshLibraryList());
});
}
else
{
SimpleMessageBox.ShowError(Window.GetWindow(this), $"Could not reload \"{SPRXPath}\" since it is not loaded.", "Error: Failed to reload SPRX.");
}
}
private void AttachProcess_Click(object sender, RoutedEventArgs e)
{
OrbisLib2.Dialog.SelectProcess.ShowDialog(GetWindow(this));
SelectProcess.ShowDialog(GetWindow(this));
}
private void DetachProcess_Click(object sender, RoutedEventArgs e)
@@ -72,9 +246,39 @@ namespace OrbisLibraryManager
TargetManager.SelectedTarget.Debug.Detach();
}
private void Refresh_Click(object sender, RoutedEventArgs e)
private void LoadSomething_Click(object sender, RoutedEventArgs e)
{
RefreshLibraryList();
}
private void KillProcess_Click(object sender, RoutedEventArgs e)
{
var currentTarget = TargetManager.SelectedTarget;
var processList = TargetManager.SelectedTarget.Process.GetList();
var process = processList.Find(x => x.ProcessId == currentTarget.Debug.GetCurrentProcessId());
if(process != null)
{
if(process.AppId > 0)
{
currentTarget.Application.Stop(process.TitleId);
}
else
{
SimpleMessageBox.ShowError(Window.GetWindow(this), $"Could not kill process \"{process.Name}\" because Orbis Suite doesnt currently support killing processes with out an appId.", "Error: Could not kill this process.");
}
}
}
private void RestartTarget_Click(object sender, RoutedEventArgs e)
{
TargetManager.SelectedTarget.Reboot();
}
private void ShutdownTarget_Click(object sender, RoutedEventArgs e)
{
TargetManager.SelectedTarget.Shutdown();
}
#endregion
}
}
@@ -1 +1 @@
2336
2371
@@ -1 +1 @@
Version 3.0.2336 Debug Build Friday January 06 2023 10:36 PM
Version 3.0.2371 Debug Build Saturday January 07 2023 8:48 PM