Классы С# для восстановления файлов?

Возможный дубликат:
Как восстановить файл из корзины с помощью С#?


Восстановление удаленных файлов в окнах

Я работаю над приложением, которое предназначено для восстановления удаленных файлов из системы (как из корзины, так и из тех, которые уже освобождены из корзины, но все еще понятных) и отформатированных дисков. Я решил использовать С# как язык, но мне трудно найти классы, которые справляются с этой проблемой. Кто-нибудь знает какие-либо классы/методы для поиска удаленных файлов, получения их или любых учебных пособий или помогает в этом вопросе. У меня мало опыта в этом вопросе, поэтому любая помощь была бы высоко оценена.

Ответ 1

Нет встроенных классов для выполнения ваших запросов.

На самом деле, удаление файлов является сложным процессом и требует очень низкого уровня знаний о вашей файловой системе. Поэтому первое, что нужно сделать, это получить информацию о диске, который содержит файл, который вы хотите восстановить. В основном вы сначала хотите узнать свою файловую систему.

Вам придется многократно использовать 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 вам необходимо понять концепцию Таблица основных файлов. На самом деле это довольно сложно. Для файловых систем FAT, которые менее сложны, но все же, вам придется некоторое время изучать FS. Начните с wikipedia.

Из дескриптора, который вы использовали CreateFile, вы теперь будете читать (необработанный доступ) байт на каждый байт (фактически по секторам) на диск, чтобы получить нужную информацию с помощью ReadFile.

// 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 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 и искать удаленные файлы...

Я не буду объяснять весь процесс здесь. См. эту ссылку для примера.

Так что удачи с этим:)

Теперь вы, вероятно, захотите использовать стороннее приложение, которое уже делает все это и использует его из своей собственной программы (средство командной строки, как сказано в комментариях).