C#类取消删除文件?

时间:2012-01-11 12:25:17

标签: c# data-recovery

  

可能重复:
  How do I restore a file from the recycle bin using C#?
  Recovering deleted file on windows

我正在开发一个应用程序,用于从系统中恢复已删除的文件(包括回收站中的文件和已从回收站中清空但仍可理解的文件)和格式化的驱动器。我决定用c#作为语言,但是我很难找到解决这个问题的类。有没有人知道任何用于查找已删除文件,检索它们或任何教程或帮助解决此问题的类/方法。我对这个问题没什么经验,所以任何帮助都会受到高度赞赏。

1 个答案:

答案 0 :(得分:43)

没有内置的课程来执行您的要求

实际上,取消删除文件是一个很难的过程,它需要对文件系统的知识水平很低。因此,首先要做的是获取有关包含要取消删除的文件的驱动器的信息。基本上你首先想知道它的文件系统。

你必须经常使用P / Invoke。首先获得目标驱动器的句柄:

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern IntPtr CreateFile(
    string lpFileName,
    uint dwDesiredAccess,
    uint dwShareMode,
    IntPtr lpSecurityAttributes,
    uint dwCreationDisposition,
    int dwFlagsAndAttributes,
    IntPtr hTemplateFile);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool GetVolumeInformationByHandleW(
    IntPtr hDisk,
    StringBuilder volumeNameBuffer,
    int volumeNameSize,
    ref uint volumeSerialNumber,
    ref uint maximumComponentLength,
    ref uint fileSystemFlags,
    StringBuilder fileSystemNameBuffer,
    int nFileSystemNameSize);

// Gets a handle to the drive
// Note: use CloseHandle to close the handle you opened once work is done
IntPtr hDrive = NativeMethods.CreateFile(
    string.Format("\\\\.\\{0}:", DriveLetter)
    GenericRead,
    Read | Write,
    IntPtr.Zero,
    OpenExisting,
    0,
    IntPtr.Zero);

// Then gets some information about the drive
// The following function requires Vista+
// Use GetVolumeInformation for older systems
const int VolumeNameSize = 255;
const int FileSystemNameBufferSize = 255;
StringBuilder volumeNameBuffer = new StringBuilder(VolumeNameSize);
uint volumeSerialNumber = 0;
uint maximumComponentLength = 0;
uint fileSystemFeatures;
StringBuilder fileSystemNameBuffer = new StringBuilder(FileSystemNameBufferSize);

GetVolumeInformationByHandleW(
    hDrive,
    volumeNameBuffer,
    VolumeNameSize,
    ref volumeSerialNumber,
    ref maximumComponentLength,
    ref fileSystemFeatures,
    fileSystemNameBuffer,
    FileSystemNameBufferSize);

// Now you know the file system of your drive
// NTFS or FAT16 or UDF for instance
string FileSystemName = fileSystemNameBuffer.ToString();

获得文件系统的名称后,您必须手动从驱动器中读取原始数据。 您将完全阅读的内容取决于驱动器的文件系统。无论如何,你必须获得相关硬盘的句柄:

// Gets a handle to the physical disk
IntPtr hDisk = CreateFile(string.Format("\\\\.\\PhysicalDrive{0}", diskNumber),
    GenericRead,
    Read | Write,
    0,
    OpenExisting,
    0,
    IntPtr.Zero);

现在,你需要了解很多关于文件系统的部分...... 对于NTFS文件系统,您必须了解Master File Table的概念。实际上,这很难。 对于FAT文件系统来说,这不那么复杂,但仍然需要研究FS一段时间。从wikipedia开始。

从使用CreateFile的句柄中,您现在将每个字节(实际上逐扇区)的(原始访问)字节读取到磁盘中,以使用ReadFile获取所需的信息。 / p>

// Used to read in a file
[DllImport("kernel32.dll")]
public static extern bool ReadFile(
    IntPtr hFile,
    byte[] lpBuffer,
    uint nNumberOfBytesToRead,
    ref uint lpNumberOfBytesRead,
    IntPtr lpOverlapped);

// Used to set the offset in file to start reading
[DllImport("kernel32.dll")]
public static extern bool SetFilePointerEx(
    IntPtr hFile,
    long liDistanceToMove,
    ref long lpNewFilePointer,
    uint dwMoveMethod);

// Set offset
int bufferSize = 512;
byte[] buffer = new byte[bufferSize];
SetFilePointerEx(
    hDisk,
    offset,
    ref pt,
    FileBegin);

// Read a whole sector
// Note that you can't read less than a whole sector of your physical disk. Usually it's 512 bytes,
// but you'll have to retrieve this information from the disk geometry. If you're interested, I can provide you
// some code. It requires the use of the IOCTL_DISK_GET_DRIVE_GEOMETRY control code.
uint read = 0;
ReadFile(
    hDisk,
    buffer,
    bufferSize,
    ref read,
    IntPtr.Zero);

对于NTFS,首先要获得MFT的起始扇区....然后你必须“解析”MFT并寻找已删除的文件......

我不会在这里解释整个过程。有关示例,请参阅this link

祝你好运:)

现在您可能想要使用已经完成所有这些工作的第三方应用程序并在您自己的程序中使用它(命令行工具,如评论中所述)。

相关问题