用C#访问硬盘物理扇区和逻辑扇区的方法
2010-10-28 21:25
597 查看
因为API要用到一些宏定义和枚举变量,所以这里先定义一下:
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;
private const uint OPEN_EXISTING = 3;
public enum EMoveMethod : uint
{
Begin = 0,
Current = 1,
End = 2
}
导入需要用到的API函数:
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern uint SetFilePointer(
[In] SafeFileHandle hFile,
[In] int lDistanceToMove,
IntPtr lpDistanceToMoveHigh,
[In] EMoveMethod dwMoveMethod);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile(
[In] SafeFileHandle hFile,
[Out] byte[] lpBuffer,
uint nNumberOfBytesToRead,
out uint lpNumberOfBytesRead,
IntPtr lpOverlapped);
[DllImport("kernel32.dll")]
static extern bool WriteFile(
[In] SafeFileHandle hFile,
byte[] lpBuffer,
uint nNumberOfBytesToWrite,
out uint lpNumberOfBytesWritten,
IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern SafeFileHandle CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
读写<逻辑>扇区:
public void ReadSector([Out] byte[] ReturnByte, int SectorIndex)
{
uint dwCB;
if (SectorIndex > _SectorLength) return;
SafeFileHandle DirverHandle = CreateFile("\\\\.\\" + DirverName.Trim(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
SetFilePointer(DirverHandle, SectorIndex * 512, IntPtr.Zero, EMoveMethod.Begin);
ReadFile(DirverHandle, ReturnByte, 512, out dwCB, IntPtr.Zero);
DirverHandle.Close();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
public void WritSector(byte[] SectorBytes, int SectorIndex)
{
uint dwCB;
if (SectorBytes.Length != 512) return;
if (SectorIndex > _SectorLength) return;
SafeFileHandle DirverHandle = CreateFile("\\\\.\\" + DirverName.Trim(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
SetFilePointer(DirverHandle, SectorIndex * 512, IntPtr.Zero, EMoveMethod.Begin);
WriteFile(DirverHandle, SectorBytes, 512, out dwCB, IntPtr.Zero);
DirverHandle.Close();
}
上面用到的 DirverName 就是盘符,例如"C:"或者"D:"之类。读写到的是逻辑扇区,假如你要读写MRB,那就要使用下面的方法读写磁盘的物理扇区。
读写物理扇区:
先看下面这幅图(硬盘管理器可以看到):
红色框里的数字表示:磁盘序号(不是序列号);
天蓝色框表示:盘符;
黄色框表示:分区,分区的序号是从0开始,每个物理磁盘的分区序号都是从0开始计算。
在读写物理扇区时,需要用到磁盘序号,下一节记录怎样通过盘符获取磁盘序号的,因为一般网上找到的都是获取盘符的办法,之前这个问题差点搞疯了。
程序提到的PhysicalDrive2里的2就是磁盘序号。
创建句柄:
SafeFileHandle hdnl = CreateFile("\\\\.\\PhysicalDrive2", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
创建完句柄后读写就和操作逻辑扇区一样了,调用ReadFile/WriteFile,然后传入这个句柄就可以。
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;
private const uint OPEN_EXISTING = 3;
public enum EMoveMethod : uint
{
Begin = 0,
Current = 1,
End = 2
}
导入需要用到的API函数:
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern uint SetFilePointer(
[In] SafeFileHandle hFile,
[In] int lDistanceToMove,
IntPtr lpDistanceToMoveHigh,
[In] EMoveMethod dwMoveMethod);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile(
[In] SafeFileHandle hFile,
[Out] byte[] lpBuffer,
uint nNumberOfBytesToRead,
out uint lpNumberOfBytesRead,
IntPtr lpOverlapped);
[DllImport("kernel32.dll")]
static extern bool WriteFile(
[In] SafeFileHandle hFile,
byte[] lpBuffer,
uint nNumberOfBytesToWrite,
out uint lpNumberOfBytesWritten,
IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern SafeFileHandle CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
读写<逻辑>扇区:
public void ReadSector([Out] byte[] ReturnByte, int SectorIndex)
{
uint dwCB;
if (SectorIndex > _SectorLength) return;
SafeFileHandle DirverHandle = CreateFile("\\\\.\\" + DirverName.Trim(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
SetFilePointer(DirverHandle, SectorIndex * 512, IntPtr.Zero, EMoveMethod.Begin);
ReadFile(DirverHandle, ReturnByte, 512, out dwCB, IntPtr.Zero);
DirverHandle.Close();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
public void WritSector(byte[] SectorBytes, int SectorIndex)
{
uint dwCB;
if (SectorBytes.Length != 512) return;
if (SectorIndex > _SectorLength) return;
SafeFileHandle DirverHandle = CreateFile("\\\\.\\" + DirverName.Trim(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
SetFilePointer(DirverHandle, SectorIndex * 512, IntPtr.Zero, EMoveMethod.Begin);
WriteFile(DirverHandle, SectorBytes, 512, out dwCB, IntPtr.Zero);
DirverHandle.Close();
}
上面用到的 DirverName 就是盘符,例如"C:"或者"D:"之类。读写到的是逻辑扇区,假如你要读写MRB,那就要使用下面的方法读写磁盘的物理扇区。
读写物理扇区:
先看下面这幅图(硬盘管理器可以看到):
红色框里的数字表示:磁盘序号(不是序列号);
天蓝色框表示:盘符;
黄色框表示:分区,分区的序号是从0开始,每个物理磁盘的分区序号都是从0开始计算。
在读写物理扇区时,需要用到磁盘序号,下一节记录怎样通过盘符获取磁盘序号的,因为一般网上找到的都是获取盘符的办法,之前这个问题差点搞疯了。
程序提到的PhysicalDrive2里的2就是磁盘序号。
创建句柄:
SafeFileHandle hdnl = CreateFile("\\\\.\\PhysicalDrive2", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
创建完句柄后读写就和操作逻辑扇区一样了,调用ReadFile/WriteFile,然后传入这个句柄就可以。
相关文章推荐
- 使程序访问物理硬盘的N种方法
- Linux主机VMWare访问物理硬盘方法
- [C#] Control.Invoke方法和跨线程访问控件
- windows NT/2000读写物理,逻辑磁盘扇区
- C#用ado.net访问EXCEL的常见问题及解决方法
- windows 2008 下C#调用office组件访问拒绝的解决方法(failed due to the following error: 80070005 拒绝访问)
- [C#]如何访问及调用类中私有成员及方法
- C#线程同步的几种方法 访问地址
- C#使用ADO.Net部件来访问Access数据库的方法
- T-sql语句修改SQL Server数据库逻辑名、数据库名、物理名的方法
- c#如何获得cpu,硬盘的物理序列号
- C#中internal关键字是什么意思?什么叫做“只能在包含它的程序集中访问该方法”
- 双击硬盘分区提示拒绝访问的解决方法
- Linux中硬盘物理扇区 与文件系统文件对应关系
- VS2008(C#)子页嵌套母版页的控件访问方法(一)
- C#操作FTP报错,远程服务器返回错误:(550)文件不可用(例如,未找到文件,无法访问文件)的解决方法
- C#与数据库访问技术总结(八)之ExecuteNonQuery方法
- C#匿名方法的应用二则–实现异常Retry机制和WinForm线程安全访问
- C# web应用程序不能访问app_code下类的原因以及解决方法
- JavaScript中访问C#变量及方法