Question

I'm trying to read memory via ReadProcessMemory(), then store the read value in a float (it's definitely a float in memory, I have verified it with another utility) for later reference, but everything I've tried (BitConverter, Marshal.Copy(), etc.) seems to fail.

I've looked at a number of examples and I'm just not sure what I'm failing to understand.

I made a short program to test the concept. I'm aware of other techniques to accomplish this task, but I'm having trouble with them as well, so I'm just focusing on this right now. Basically I store (known) bytes from a float value in an array of 4 bytes, point to it via an IntPtr, and then use Marshal.Copy() to try to convert from the IntPtr to a float:

const int FLOAT_SIZE = 4;
byte[] baSource = new byte[FLOAT_SIZE];
IntPtr ipIntermediate = Marshal.AllocHGlobal(sizeof(float));
float[] faDest = new float[1];

baSource[0] = 0xA7;
baSource[1] = 0x68;
baSource[2] = 0xB9;
baSource[3] = 0x44;

ipIntermediate = ((IntPtr)(baSource[0]));
Marshal.Copy(ipIntermediate, faDest, 0, 1); // causes AccessViolation exception

I'm running Windows 7 64 bit. I'm currently targeting this build for x86, but have also tried 'Any CPU' only to get the same result. Endianness doesn't seem to be the issue either.

Any help would be greatly appreciated.

Was it helpful?

Solution

((IntPtr)(baSource[0])) means: take first element of array, and convert it to IntPtr. What you actually want: get an address of the first element of byte array. You can use unsafe code or GCHandle to achieve this:

const int FLOAT_SIZE = 4;
byte[] baSource = new byte[FLOAT_SIZE];
float[] faDest = new float[1];

baSource[0] = 0xA7;
baSource[1] = 0x68;
baSource[2] = 0xB9;
baSource[3] = 0x44;

var gch = GCHandle.Alloc(baSource, GCHandleType.Pinned);
try
{
    var source = gch.AddrOfPinnedObject();
    Marshal.Copy(source, faDest, 0, 1);
}
finally
{
    gch.Free();
}

OTHER TIPS

Probably because IntPtr is a pointer so it's interpreted as a pointer, not data, in your call to Marshal.Copy.

Note that there's a much simpler way to build a float from its constituent bytes:

float f2 = BitConverter.ToSingle(byteArray, 0);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top