I have an application that works with physical memory snapshots (for example, VMware VMEM files). Among other things, it can read processes/modules out of the snapshot by virtual rather than physical address. This involves reconstructing the module 4KB at a time through the page table, which, in turn, means a lot of calls to the Stream’s Seek() method.
For reasons I’m not sure of, these calls to Seek() bog things down dramatically. As a result, I’m looking for a way around them — or at least, a way around the managed Seek() implementation. My best guess is to PInvoke SetFilePointer and work with that directly, but in order to do that I need to get the IntPtr/SafeFileHandle for the Stream. I have a few restrictions:
-
The API I’m working with is limited to .NET 3.5, so unfortunately MemoryMappedFile isn’t an option.
-
I can’t use a FileStream (which already has a private SafeFileHandle field that can be accessed with reflection) or PInvoke CreateFile() to get at the snapshot another way — the API includes a BinaryReader that has an exclusive lock on the snapshot.
Of course, unlike FileStream, neither BinaryReader nor its underlying Stream have a reference to the file handle. But certainly one must exist? In which case, how do I go about acquiring it?
There’s no file handle for
Streambecause it’s an abstract class. A class implementingStreammay or may not use a file handle —FileStreamdoes, since it reads data from a file, butMemoryStream, for example, does not.To get the underlying file handle (in this case a
SafeFileHandle) of aBinaryReaderwhoseStreamis aFileStream, use reflection to accessprivate SafeFileHandle _handle, like so:On a side note: neither direct calls to
SetFilePointer()norMemoryMappedFilehelped in this case. It seems there’s no fast way to handle random disk access at the volume I’m using it (millions of consecutive calls).