我正在尝试使 kernel32 的 ReadFile 工作,因为本机 c# 替代品很慢,因为...
以下代码运行了几次,然后突然只给出“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。”
我认为重新启动服务器会使其工作几次,然后再出现相同的错误,但似乎我错了,无论我现在做什么都会发生..
这是我的代码:
using System.Runtime.InteropServices;
private WinFileIO.WinFileIO _winFile;
_winFile = new WinFileIO.WinFileIO(new byte[bufferSize]);
_winFile.OpenForReading(_fileInfo.FullName);
public WinFileIO(Array Buffer)
{
PinBuffer(Buffer);
pHandleRead = IntPtr.Zero;
pHandleWrite = IntPtr.Zero;
bufferSize = Buffer.GetLength(0);
}
private void PinBuffer(Array Buffer)
{
UnpinBuffer();
gchBuf = GCHandle.Alloc(Buffer, GCHandleType.Pinned);
IntPtr pAddr = Marshal.UnsafeAddrOfPinnedArrayElement(Buffer, 0);
// pBuffer is the pointer used for all of the I/O functions in this class.
pBuffer = (void*)pAddr.ToPointer();
}
public void UnpinBuffer()
{
if (gchBuf.IsAllocated)
gchBuf.Free();
}
[System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
static extern unsafe System.IntPtr CreateFile
(
string FileName, // file name
uint DesiredAccess, // access mode
uint ShareMode, // share mode
uint SecurityAttributes, // Security Attributes
uint CreationDisposition, // how to create
uint FlagsAndAttributes, // file attributes
int hTemplateFile // handle to template file
);
[System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
private unsafe static extern bool ReadFile
(
int hFile,
byte[] arraypBuffer,
int NumberOfBytesToRead,
ref int lpNumberOfBytesToRead,
int* ptr
);
[System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
static extern unsafe bool SetFilePointer
(
System.IntPtr hObject,
int lDistanceToMove,
ref int lpDistanceToMoveHigh,
EMoveMethod dwMoveMethod
);
public void OpenForReading(string FileName)
{
Close(true, false);
pHandleRead = CreateFile(FileName, 3, 3, 0, OPEN_EXISTING, 0, 0);
if (pHandleRead == System.IntPtr.Zero)
{
Win32Exception WE = new Win32Exception();
ApplicationException AE = new ApplicationException("WinFileIO:OpenForReading - Could not open file " +
FileName + " - " + WE.Message);
throw AE;
}
}
public void MoveOffset(int moveDistance, EMoveMethod moveMethod)
{
if (pHandleRead != System.IntPtr.Zero)
{
int moveDistanceHigh = 0;
SetFilePointer(pHandleRead, moveDistance, ref moveDistanceHigh, moveMethod);
}
}
public unsafe Tuple<int, byte[]> ReadChunk(int bufferSize, int offset)
{
int bytesRead = 0;
byte[] bufBytes = new byte[bufferSize];
MoveOffset(offset, EMoveMethod.Begin);
int pointer = (int)Marshal.PtrToStructure(pHandleRead, typeof(int));
if (ReadFile(pointer, bufBytes, bufferSize, ref bytesRead, null))
{
byte[] outBytes = new byte[bytesRead];
Array.Copy(bufBytes, outBytes, bytesRead);
return new Tuple<int, byte[]>(bytesRead, outBytes);
}
return null;
}
我认为这就是所有相关的代码。
我猜这与 CreateFile 和 ReadFile 签名不完全兼容(IntPtr 与 int)、IntPtr 的 Marshal.PtrToStructure 没有指向它应该指向的位置、或者内存没有被释放或什么有关?不过,重启后它对几次尝试都不起作用的事实让我感到困惑。
有人发现任何明显的东西或有什么我可以研究的建议吗?
谢谢
编辑:您可能会注意到,这是一种不同方法的混搭,我不再使用固定缓冲区,因为我努力让缓冲区的内容像我想要的那样读取。
Edit2:堆栈跟踪说这是问题所在:
at System.Runtime.InteropServices.Marshal.PtrToStructure(IntPtr ptr, Type structureType)