重複の可能性:
Windows内の一意のファイル識別子
コンピューター上の特定のファイルの一意の識別子を取得する必要がありますが、Win32GetFileInformationByHandle関数にしか遭遇していません。でこれをどのように達成できますか。ネットフレームワーク?
更新:ファイルが移動、更新、名前変更された場合などに変更されない永続的なIDが必要です。
Update2:フォルダで同じことをどのように達成できますか?
重複の可能性:
Windows内の一意のファイル識別子
コンピューター上の特定のファイルの一意の識別子を取得する必要がありますが、Win32GetFileInformationByHandle関数にしか遭遇していません。でこれをどのように達成できますか。ネットフレームワーク?
更新:ファイルが移動、更新、名前変更された場合などに変更されない永続的なIDが必要です。
Update2:フォルダで同じことをどのように達成できますか?
これが、この回答からコピーしたAshleyHendersonのコードです。これは、両方が同じ一意の識別子を返す2つのアプローチを意味します。
public class WinAPI
{
[DllImport("ntdll.dll", SetLastError = true)]
public static extern IntPtr NtQueryInformationFile(IntPtr fileHandle, ref IO_STATUS_BLOCK IoStatusBlock, IntPtr pInfoBlock, uint length, FILE_INFORMATION_CLASS fileInformation);
public struct IO_STATUS_BLOCK
{
uint status;
ulong information;
}
public struct _FILE_INTERNAL_INFORMATION {
public ulong IndexNumber;
}
// Abbreviated, there are more values than shown
public enum FILE_INFORMATION_CLASS
{
FileDirectoryInformation = 1, // 1
FileFullDirectoryInformation, // 2
FileBothDirectoryInformation, // 3
FileBasicInformation, // 4
FileStandardInformation, // 5
FileInternalInformation // 6
}
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetFileInformationByHandle(IntPtr hFile,out BY_HANDLE_FILE_INFORMATION lpFileInformation);
public struct BY_HANDLE_FILE_INFORMATION
{
public uint FileAttributes;
public FILETIME CreationTime;
public FILETIME LastAccessTime;
public FILETIME LastWriteTime;
public uint VolumeSerialNumber;
public uint FileSizeHigh;
public uint FileSizeLow;
public uint NumberOfLinks;
public uint FileIndexHigh;
public uint FileIndexLow;
}
}
public class Test
{
public ulong ApproachA()
{
WinAPI.IO_STATUS_BLOCK iostatus=new WinAPI.IO_STATUS_BLOCK();
WinAPI._FILE_INTERNAL_INFORMATION objectIDInfo = new WinAPI._FILE_INTERNAL_INFORMATION();
int structSize = Marshal.SizeOf(objectIDInfo);
FileInfo fi=new FileInfo(@"C:\Temp\testfile.txt");
FileStream fs=fi.Open(FileMode.Open,FileAccess.Read,FileShare.ReadWrite);
IntPtr res=WinAPI.NtQueryInformationFile(fs.Handle, ref iostatus, memPtr, (uint)structSize, WinAPI.FILE_INFORMATION_CLASS.FileInternalInformation);
objectIDInfo = (WinAPI._FILE_INTERNAL_INFORMATION)Marshal.PtrToStructure(memPtr, typeof(WinAPI._FILE_INTERNAL_INFORMATION));
fs.Close();
Marshal.FreeHGlobal(memPtr);
return objectIDInfo.IndexNumber;
}
public ulong ApproachB()
{
WinAPI.BY_HANDLE_FILE_INFORMATION objectFileInfo=new WinAPI.BY_HANDLE_FILE_INFORMATION();
FileInfo fi=new FileInfo(@"C:\Temp\testfile.txt");
FileStream fs=fi.Open(FileMode.Open,FileAccess.Read,FileShare.ReadWrite);
WinAPI.GetFileInformationByHandle(fs.Handle, out objectFileInfo);
fs.Close();
ulong fileIndex = ((ulong)objectFileInfo.FileIndexHigh << 32) + (ulong)objectFileInfo.FileIndexLow;
return fileIndex;
}
}
ファイル形式はあなたの管理下にないと思います(そうでなければ、UUIDを生成してそこに保存します)。
ファイルオブジェクトID
NTFSは、ファイルレベルでオブジェクトIDをサポートします。FSCTL_CREATE_OR_GET_OBJECT_IDを参照してください。私はそれらを推薦するためにそれらを使用していませんが、それは探索するための有望なもののようです。
代替データストリーム(下記)と同様に、NTFS以外のメディア(「通常の」メモリスティック、CD、DVD、フラッシュカード、場合によっては一部のUSBディスクなど)にコピーすると、失われる可能性があります。また、一部のアプリケーションは、保存時にファイルを再作成するときに混乱する可能性があります。
分散リンク追跡サービス
Distributed Link Tracking Serviceは、ファイルへのリンクを追跡し、ファイルが移動されたときにそれらを修復するために、ファイルオブジェクトIDを使用します。
AFAIK分散リンク追跡サービスには、サーバーのドメインコントローラーが必要です。繰り返しますが、私はこれについて実際的な経験がありません。
NTFSでは、UUIDを作成して代替データストリームに保存することもできます。
警告:
Officeなどの一部のドキュメント形式では、カスタムドキュメントプロパティを使用できます。
これは明らかに制限されていますが、同様のメカニズムを他のファイルタイプに便乗させることもできます。(たとえば、多くの画像形式では、読者が無視する必要のある「カスタム」チャンクを追加/書き換えることができます)
FileFromIDとIDFromFile
DLTSを除くすべてのソリューションではIDFromFile
ルックアップのみが許可されます。つまり、移動した(または削除された)ファイルを見つけるには、すべての潜在的なドライブを検索する必要があります。
DLTSの場合、「直接API」の方法がない場合は、DLTS対応のショートカットをアプリケーション固有のフォルダーに保存し、ファイルが移動されたときにサービスがショートカットを修復することを期待できます。
ファイルのMD5ハッシュを取得できます。次の例を見てください。
string GetMD5HashFromFile(string fileName)
{
FileStream file = new FileStream(fileName, FileMode.Open);
MD5 md5 = new MD5CryptoServiceProvider();
byte[] retVal = md5.ComputeHash(file);
file.Close();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
return sb.ToString();
}
これにより、ファイルごとに一意の識別子が返されます。