2008-09-01 9 views
11

.Netでディスクを直接読み取ることはできますか?直接私は、ファイルシステムをバイパスしてデバイスを経由することを意味します。私は、デバイスを「\ Device \ Ide \ IdeDeviceP2T0L0-1」などのように開いて、これについて説明します。.Netを使って直接ディスクを読み取るにはどうすればよいですか?

.NET APIを使用してデバイスを開くことができない場合は、使用するWin32 APIを知っておくと便利です。

+0

私にも同様の質問があります。お手伝いできますか? [CreateFile: "アクセスが拒否されました"管理者権限でも - Win7](http://stackoverflow.com/q/8694713/341970) – Ali

答えて

4

CreateFileは、ダイレクトディスクアクセスをサポートしています。 「物理ディスクとボリューム」の注記を読んでください。呼び出しをP /呼び出しできるはずです。

VistaとServer 2008にはseverely restrictedがあります。

+0

私は似たような質問がありますか? [CreateFile: "アクセスが拒否されました"管理者権限でも - Win7](http://stackoverflow.com/q/8694713/341970) – Ali

8

Mark、ありがとう、私は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(); 
     } 

標準免責事項が適用されたクラスを使用する例は、このコードは、あなたの健康に有害かもしれません。

1

男。すべてのことマーシャリングやもので、ちょうどCでDLLを作成し、.NET

を見送るない、なぜあなたはその後、P /あなたのdllを呼び出し、それをはるかに簡単に時間を持つことができ、すべての

0

マークの答えに同意します。ユーザーアカウント制御が有効になっている場合(Windows Vista以上の既定値)、プログラムは管理者特権で昇格された状態で実行されている必要があります。あなたのプログラムがちょうど少数のユーザーのために使用されている場合は、実行可能ファイルを右クリックして「管理者として実行」を選択するようにユーザーに要求することができます。それ以外の場合は、マニフェストファイルをプログラムにコンパイルし、マニフェストで、プログラムを昇格させる必要があることを指定します(詳細については、 "requestedExecutionLevel requireAdministrator"を検索してください)。

関連する問題