C
C#Matt

✅ Exception Handling for NRE without modifying every call.

I have a ReadData function which reads the memory of a process. If the process exits or crashes during the read, an exception is thrown and control is handed to the catch block. However, the calling function (the function that calls ReadData) can sometimes throw an NRE if the ReadData was aborted and returned null instead of a byte[]. How can I avoid the NREs without needing to change every single call of ReadData? Ideally I would abort the calling function as if it had never been called but I know that would require a large scale rewrite. I have toyed with the idea of modifying the ReadData signature to return a tuple of type (byte[], bool) and changing the behaviour of the calling function depending on the success of the ReadData (bool) but this would also require custom behaviour for every call. There are about 20 calls and I figure adding custom behaviour or exception handling for all of them is inefficient and bad practice. Any solutions?
E
ero415d ago
ReadData should really just be
unsafe bool TryRead<T>(nint handle, nint address, out T result)
where T : unmanaged
{
fixed (T* pResult = &result)
{
nuint nSize = (nuint)bufferSize, nRead;
return ReadProcessMemory(handle, (void*)address, pResult, nSize, &nRead)
&& nRead == nSize;
}
}
unsafe bool TryRead<T>(nint handle, nint address, out T result)
where T : unmanaged
{
fixed (T* pResult = &result)
{
nuint nSize = (nuint)bufferSize, nRead;
return ReadProcessMemory(handle, (void*)address, pResult, nSize, &nRead)
&& nRead == nSize;
}
}
no throwing involved and you know immediately whether or not the call failed or succeeded from the return value you could even make it an extension method on Process;
static unsafe bool TryRead<T>(this Process proc, nint address, out T result)
where T : unmanaged
{
if (proc is null || proc.Handle == 0)
{
result = default;
return false;
}

fixed (T* pResult = &result)
{
nuint nSize = (nuint)bufferSize, nRead;
return ReadProcessMemory(proc.Handle, (void*)address, pResult, nSize, &nRead)
&& nRead == nSize;
}
}
static unsafe bool TryRead<T>(this Process proc, nint address, out T result)
where T : unmanaged
{
if (proc is null || proc.Handle == 0)
{
result = default;
return false;
}

fixed (T* pResult = &result)
{
nuint nSize = (nuint)bufferSize, nRead;
return ReadProcessMemory(proc.Handle, (void*)address, pResult, nSize, &nRead)
&& nRead == nSize;
}
}
and then you can simply do
var process = /* */;
Console.WriteLine(process.TryRead<int>(0xDEADBEEF, out int result));
Console.WriteLine(result);
var process = /* */;
Console.WriteLine(process.TryRead<int>(0xDEADBEEF, out int result));
Console.WriteLine(result);
A
Accord414d ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
M
Matt413d ago
I like this solution and I'm going to try it but I'm confused by the line
nuint nSize = (nuint)bufferSize, nRead;
nuint nSize = (nuint)bufferSize, nRead;
bufferSize is never declared?
E
ero413d ago
ah, my bad i just copy pasted the code from another method
nuint nSize = (nuint)sizeof(T), nRead;
nuint nSize = (nuint)sizeof(T), nRead;
M
Matt413d ago
Thank you, there's also a clash between my current declaration of the ReadProcessMemory method and the call to it. I'm assuming I need to change my declaration's signature?
public static extern bool ReadProcessMemory(IntPtr hProcess, int lpBaseAddress, byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead);
public static extern bool ReadProcessMemory(IntPtr hProcess, int lpBaseAddress, byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead);
E
ero413d ago
yes https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-readprocessmemory
BOOL ReadProcessMemory(
[in] HANDLE hProcess,
[in] LPCVOID lpBaseAddress,
[out] LPVOID lpBuffer,
[in] SIZE_T nSize,
[out] SIZE_T *lpNumberOfBytesRead
);
BOOL ReadProcessMemory(
[in] HANDLE hProcess,
[in] LPCVOID lpBaseAddress,
[out] LPVOID lpBuffer,
[in] SIZE_T nSize,
[out] SIZE_T *lpNumberOfBytesRead
);
this is the real signature HANDLE can be a nint (or IntPtr, they're identical, nint just doesn't require using System;) LPVOID and LPCVOID are void* SIZE_T is nuint (or UIntPtr) oh yeah and BOOL is int so the c# signature is
[DllImport("kernel32")]
internal static static extern int ReadProcessMemory(
nint hProcess,
void* lpBaseAddress,
void* lpBuffer,
nuint nSize,
nuint* lpNumberOfBytesRead);
[DllImport("kernel32")]
internal static static extern int ReadProcessMemory(
nint hProcess,
void* lpBaseAddress,
void* lpBuffer,
nuint nSize,
nuint* lpNumberOfBytesRead);
static unsafe bool TryRead<T>(this Process proc, nint address, out T result)
where T : unmanaged
{
if (proc is null || proc.Handle == 0)
{
result = default;
return false;
}

fixed (T* pResult = &result)
{
nuint nSize = (nuint)sizeof(T), nRead;
return ReadProcessMemory(proc.Handle, (void*)address, pResult, nSize, &nRead) != 0
&& nRead == nSize;
}
}
static unsafe bool TryRead<T>(this Process proc, nint address, out T result)
where T : unmanaged
{
if (proc is null || proc.Handle == 0)
{
result = default;
return false;
}

fixed (T* pResult = &result)
{
nuint nSize = (nuint)sizeof(T), nRead;
return ReadProcessMemory(proc.Handle, (void*)address, pResult, nSize, &nRead) != 0
&& nRead == nSize;
}
}
M
Matt413d ago
Thank you. I guess I need to declare the method as unsafe too
E
ero413d ago
ah, yeah or the class
M
Matt413d ago
better option
E
ero413d ago
unsafe class Win32
{

}
unsafe class Win32
{

}
or WinApi or Win32Api or use CsWin32 (NuGet)
M
Matt413d ago
this seems to work. Sorry to be a pain but I assume there is also a solution for the write function which is similar?
E
ero413d ago
almost the exact same
M
Matt413d ago
Thank you, I'll figure that one out
E
ero413d ago
[DllImport("kernel32")]
internal static extern int WriteProcessMemory(
nint hProcess,
void* lpBaseAddress,
void* lpBuffer,
nuint nSize,
nuint* lpNumberOfBytesWritten);
[DllImport("kernel32")]
internal static extern int WriteProcessMemory(
nint hProcess,
void* lpBaseAddress,
void* lpBuffer,
nuint nSize,
nuint* lpNumberOfBytesWritten);
static unsafe bool TryWrite<T>(this Process proc, nint address, T data)
where T : unmanaged
{
if (proc is null || proc.Handle == 0)
{
result = default;
return false;
}

fixed (T* pData = &data)
{
nuint nSize = (nuint)sizeof(T), nWritten;
return WriteProcessMemory(proc.Handle, (void*)address, pData, nSize, &nWritten) != 0
&& nWritten == nSize;
}
}
static unsafe bool TryWrite<T>(this Process proc, nint address, T data)
where T : unmanaged
{
if (proc is null || proc.Handle == 0)
{
result = default;
return false;
}

fixed (T* pData = &data)
{
nuint nSize = (nuint)sizeof(T), nWritten;
return WriteProcessMemory(proc.Handle, (void*)address, pData, nSize, &nWritten) != 0
&& nWritten == nSize;
}
}
M
Matt413d ago
oh damn. Thank you 🙂
E
ero413d ago
i'm not sure whether the handle check might be pointless you can possibly just remove that one
M
Matt413d ago
^ it's not for my use case. I'll get on implementing this and hope it's less overhead and things speed up. Otherwise I have the nasty task of figuring out what's slowing my app down
Want results from more Discord servers?
Add your server
More Posts
✅ please help idk what to do or what i didSeverity Code Description Project File Line Suppression State Error Project❔ Better user experience inputting commandsHow would I get input from a user, the fancy way? What I mean is that for example when a user types ❔ Return in the middle of a methodIs it ok? I think that it improves readability and performance, but a professor I know argues that i❔ Can't build a MSIX Package for a WPF app❔ Should photo urls be sent paginated to the frontend?So, any given property has a collection of photos in a photo album... they are saved as urls in the ❔ c# wpf textbox access violationHello does anyone know how can i edit the TextBox1.Text within the Task.run so i don't have an acces❔ Help with choosing between ArrayList and other types of collectionsI was challenged to make a pokémon styled game without using classes and I wanted to know better way❔ How can you create a string that creates random characters?Title ^ (Console application)❔ ✅ abstract-Parent and Child static overrides?How do I redeclare an objects element which needs be from a static context in a child class? I have❔ Asking if someone wants to be part of my project (Valorant Discord Rich Presence)Heyheyhey Does some people here play Valorant and want to help me create a Discord Rich Presence usi❔ asp.net web app debug in vscodelI am trying to find out what the database is returning for a specific variable on one of my view pa❔ <AuthorizeView> not workingI am currently making a Blazor Server App with a Custom Authentication. I can give my current user r❔ ✅ Update Dropdown options in Unity without loosing selected optionI have written a StatSelector class. The purpose is to let the user assign generated values to his c❔ How can I store history of each tree node in memory without any leaks?```cpp public class TreeNode { protected TreeNode(string part) : this(part, -1, null) {} ❔ ✅ Lifetime of variable referenced in Func<>In some of my tests, I'm creating tables as I go, and then dropping the tables at the end of the tes❔ Visual Studios, How to make a list of students and make a teacher type students name or type info❔ Hi, guys I am trying to connect my unity project to SignalR and having some issues.this is the error i receive when I hit play Error An error occurred while sending the request Unity❔ OneOf deserializer for Newtonsoft JSONI have a lot of data-contracts generated from code, which utilizes `OneOf<...>` (<https://github.com❔ As loop value increments, increment variable nameI have a loop to insert values into 5 objects of employees named employee1,employee2... Is there a ✅ Binary Search Treehttps://www.hackerearth.com/practice/data-structures/trees/binary-search-tree/practice-problems/algo