我正在尝试通过ReadProcessMemory()读取内存,然后将读取值存储在一个浮点数中(它肯定是内存中的一个浮点数,我已经用另一个实用程序验证了它)供以后参考,但是我尝试了一切( BitConverter,Marshal.Copy()等)似乎都失败了。
我看了很多例子,我只是不确定我没理解的是什么。
我做了一个简短的程序来测试这个概念。我知道其他技术可以完成这项任务,但我也遇到了麻烦,所以我现在只关注这个问题。基本上我从浮点值中存储(已知)4个字节的数组中的字节,通过IntPtr指向它,然后使用Marshal.Copy()尝试从IntPtr转换为浮点数:
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
我正在运行Windows 7 64位。我目前正在针对x86进行此构建,但也尝试使用“Any CPU”来获得相同的结果。 Endianness似乎也不是问题。
非常感谢任何帮助。
答案 0 :(得分:2)
((IntPtr)(baSource[0]))
表示:获取数组的第一个元素,并将其转换为IntPtr
。你真正想要的是:获取字节数组的第一个元素的地址。您可以使用不安全的代码或GCHandle
来实现此目的:
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();
}
答案 1 :(得分:0)
可能是因为IntPtr是一个指针,所以在你对Marshal.Copy的调用中它被解释为指针,而不是数据。
请注意,有一种更简单的方法可以从其组成字节构建浮点数:
float f2 = BitConverter.ToSingle(byteArray, 0);