14

重複の可能性:
C#を使用してごみ箱からファイルを復元するにはどうすればよいですか?
Windowsで削除されたファイルを回復する

私は、システムから削除されたファイル(ごみ箱からのファイルと、ごみ箱からすでに空になっているがまだ理解できるファイルの両方)とフォーマットされたドライブを回復することを目的としたアプリケーションに取り組んでいます。言語としてc#を選択しましたが、この問題を処理するクラスを見つけるのに苦労しています。削除されたファイルを検索したり、それらを取得したり、チュートリアルや問題を解決したりするためのクラス/メソッドを知っている人はいますか?私はこのテーマについてほとんど経験がないので、どんな助けでも強くいただければ幸いです。

4

1 に答える 1

49

あなたが求めたことを実行するための組み込みのクラスはありません

実際、ファイルの削除を取り消すのは難しいプロセスであり、ファイルシステムに関する非常に低いレベルの知識が必要です。したがって、最初に行うことは、削除を取り消すファイルを含むドライブに関する情報を取得することです。基本的に、最初にそのファイルシステムを知りたいと思います。

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を研究する必要があります。ウィキペディアから始めます。

を使用して取得したハンドルから、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'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を「解析」して、削除されたファイルを探す必要があります。

ここでは、プロセス全体については説明しません。例については、このリンクを参照してください。

それで頑張ってください:)

今、あなたはおそらく、すでにこれらすべてのことをしているサードパーティのアプリケーションを使用して、あなた自身のプログラム(コメントで述べられているようにコマンドラインツール)からそれを使用したいかもしれません。

于 2012-01-11T13:34:25.580 に答える