如何直接使用.Net读取磁盘?
时间:2020-03-05 18:46:04 来源:igfitidea点击:
可以直接用.Net读取磁盘吗?我的意思是直接通过设备绕过文件系统。我想我可以通过以下方式打开设备:" \ Device \ Ide \ IdeDeviceP2T0L0-1"。
如果无法使用.NET api打开设备,则知道使用哪个Win32 API会有所帮助。
解决方案
回答
CreateFile支持直接磁盘访问。阅读"物理磁盘和卷"下的注释。我们应该能够P /调用呼叫。
请注意,Vista和Server 2008对此进行了严格限制。
回答
太好了,谢谢马克,我忘记了CreateFile也可以打开东西。我正在查看卷管理API,但没有看到如何打开文件。
这是一个总结课程的小类。仅将SafeFileHandle传递到FileStream中也可能/正确。
using System; using System.Runtime.InteropServices; using System.IO; using Microsoft.Win32.SafeHandles; namespace ReadFromDevice { public class DeviceStream : Stream, IDisposable { public const short FILE_ATTRIBUTE_NORMAL = 0x80; public const short INVALID_HANDLE_VALUE = -1; public const uint GENERIC_READ = 0x80000000; public const uint GENERIC_WRITE = 0x40000000; public const uint CREATE_NEW = 1; public const uint CREATE_ALWAYS = 2; public const uint OPEN_EXISTING = 3; // Use interop to call the CreateFile function. // For more information about CreateFile, // see the unmanaged MSDN reference library. [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool ReadFile( IntPtr hFile, // handle to file byte[] lpBuffer, // data buffer int nNumberOfBytesToRead, // number of bytes to read ref int lpNumberOfBytesRead, // number of bytes read IntPtr lpOverlapped // // ref OVERLAPPED lpOverlapped // overlapped buffer ); private SafeFileHandle handleValue = null; private FileStream _fs = null; public DeviceStream(string device) { Load(device); } private void Load(string Path) { if (string.IsNullOrEmpty(Path)) { throw new ArgumentNullException("Path"); } // Try to open the file. IntPtr ptr = CreateFile(Path, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); handleValue = new SafeFileHandle(ptr, true); _fs = new FileStream(handleValue, FileAccess.Read); // If the handle is invalid, // get the last Win32 error // and throw a Win32Exception. if (handleValue.IsInvalid) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } } public override bool CanRead { get { return true; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return false; } } public override void Flush() { return; } public override long Length { get { return -1; } } public override long Position { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } /// <summary> /// </summary> /// <param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and /// (offset + count - 1) replaced by the bytes read from the current source. </param> /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream. </param> /// <param name="count">The maximum number of bytes to be read from the current stream.</param> /// <returns></returns> public override int Read(byte[] buffer, int offset, int count) { int BytesRead =0; var BufBytes = new byte[count]; if (!ReadFile(handleValue.DangerousGetHandle(), BufBytes, count, ref BytesRead, IntPtr.Zero)) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } for (int i = 0; i < BytesRead; i++) { buffer[offset + i] = BufBytes[i]; } return BytesRead; } public override int ReadByte() { int BytesRead = 0; var lpBuffer = new byte[1]; if (!ReadFile( handleValue.DangerousGetHandle(), // handle to file lpBuffer, // data buffer 1, // number of bytes to read ref BytesRead, // number of bytes read IntPtr.Zero )) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); ;} return lpBuffer[0]; } public override long Seek(long offset, SeekOrigin origin) { throw new NotImplementedException(); } public override void SetLength(long value) { throw new NotImplementedException(); } public override void Write(byte[] buffer, int offset, int count) { throw new NotImplementedException(); } public override void Close() { handleValue.Close(); handleValue.Dispose(); handleValue = null; base.Close(); } private bool disposed = false; new void Dispose() { Dispose(true); base.Dispose(); GC.SuppressFinalize(this); } private new void Dispose(bool disposing) { // Check to see if Dispose has already been called. if (!this.disposed) { if (disposing) { if (handleValue != null) { _fs.Dispose(); handleValue.Close(); handleValue.Dispose(); handleValue = null; } } // Note disposing has been done. disposed = true; } } } }
还有一个使用类的例子
static void Main(string[] args) { var reader = new BinaryReader(new DeviceStream(@"\.\PhysicalDrive3")); var writer = new BinaryWriter(new FileStream(@"g:\test.dat", FileMode.Create)); var buffer = new byte[MB]; int count; int loopcount=0; try{ while((count=reader.Read(buffer,0,MB))>0) { writer.Write(buffer,0,count); System.Console.Write('.'); if(loopcount%100==0) { System.Console.WriteLine(); System.Console.WriteLine("100MB written"); writer.Flush(); } loopcount++; } } catch(Exception e) { Console.WriteLine(e.Message); } reader.Close(); writer.Flush(); writer.Close(); }
适用标准免责声明,此代码可能对健康有害。
回答
男人。有了所有这些编组和东西,为什么不只用C和前传.NET编写一个dll?
然后,我们可以p /调用dll,并轻松完成所有操作