2008-09-01 35 views
11

Có thể đọc trực tiếp đĩa bằng .Net không? Bởi trực tiếp tôi có nghĩa là thông qua các thiết bị bỏ qua hệ thống tập tin. Tôi nghĩ rằng tôi sẽ đi về điều này bằng cách mở thiết bị một số cách "\ Device \ Ide \ IdeDeviceP2T0L0-1" ví dụ.Làm cách nào để đọc trực tiếp đĩa bằng .Net?

Nếu tôi không thể mở thiết bị bằng .NET api biết sử dụng API Win32 nào sẽ hữu ích.

+0

Tôi có câu hỏi tương tự, bạn có thể giúp tôi không? [CreateFile: “Truy cập bị từ chối” ngay cả với đặc quyền của Quản trị viên - Win7] (http://stackoverflow.com/q/8694713/341970) – Ali

Trả lời

4

CreateFile có hỗ trợ truy cập đĩa trực tiếp. Đọc ghi chú trong phần "Đĩa vật lý và âm lượng". Bạn sẽ có thể P/Gọi cuộc gọi.

Lưu ý rằng Vista và Server 2008 có severely restricted điều này.

+0

Tôi có một câu hỏi tương tự, bạn có thể giúp tôi không? [CreateFile: "Truy cập bị từ chối" ngay cả với đặc quyền của Quản trị viên - Win7] (http://stackoverflow.com/q/8694713/341970) – Ali

8

Tuyệt vời, cảm ơn Mark, tôi đã quên rằng CreateFile cũng mở ra mọi thứ. Tôi đã nhìn vào API quản lý khối lượng và không thấy cách mở mọi thứ.

Đây là một lớp nhỏ kết thúc mọi thứ. Nó cũng có thể có thể/chính xác để chỉ cần vượt qua SafeFileHandle vào một 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; 

      } 
     } 

    } 
} 

Và một ví dụ về cách sử dụng các lớp

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(); 
     } 

kỹ khuyến cáo tiêu chuẩn áp dụng, mã này có thể gây nguy hiểm cho sức khỏe của bạn.

1

Man. Với tất cả những gì marshalling và các công cụ, tại sao không chỉ cần viết một dll trong C và từ bỏ .NET

Bạn có thể sau đó p/gọi dll của bạn và có một thời gian dễ dàng hơn nhiều của nó tất cả

0

Đồng ý với câu trả lời của Mark. Lưu ý rằng nếu User Account Control được kích hoạt (là mặc định trên Windows Vista và cao hơn), chương trình của bạn phải được nâng lên (với quyền quản trị). Nếu chương trình của bạn chỉ được sử dụng cho một vài người dùng, bạn có thể yêu cầu người dùng nhấp chuột phải vào các tệp thi hành và chọn "Chạy với tư cách là Quản trị viên". Nếu không, bạn có thể biên dịch tệp kê khai thành chương trình và trong tệp kê khai, chỉ định rằng chương trình cần được chạy cao (tìm kiếm "requestedExecutionLevel requireAdministrator" để biết thêm thông tin).

Các vấn đề liên quan