diff --git a/src/Meziantou.Framework.Win32.ChangeJournal/FileIdentifier.cs b/src/Meziantou.Framework.Win32.ChangeJournal/FileIdentifier.cs
index 362bee30..e52149c8 100644
--- a/src/Meziantou.Framework.Win32.ChangeJournal/FileIdentifier.cs
+++ b/src/Meziantou.Framework.Win32.ChangeJournal/FileIdentifier.cs
@@ -1,6 +1,10 @@
-using System.Globalization;
+using System.ComponentModel;
+using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+using Microsoft.Win32.SafeHandles;
+using Windows.Win32;
using Windows.Win32.Storage.FileSystem;
namespace Meziantou.Framework.Win32;
@@ -28,6 +32,26 @@ internal FileIdentifier(FILE_ID_128 parentFileReferenceNumber)
{
}
+ [SupportedOSPlatform("windows6.0.6000")]
+ public unsafe static FileIdentifier FromFile(string path)
+ {
+ using var handle = File.OpenHandle(path);
+ return FromFile(handle);
+ }
+
+ [SupportedOSPlatform("windows6.0.6000")]
+ public unsafe static FileIdentifier FromFile(SafeFileHandle handle)
+ {
+ var result = new FILE_ID_INFO();
+ var pointer = Unsafe.AsPointer(ref result);
+ if (PInvoke.GetFileInformationByHandleEx(handle, FILE_INFO_BY_HANDLE_CLASS.FileIdInfo, pointer, (uint)sizeof(FILE_ID_INFO)))
+ {
+ return new FileIdentifier(result.FileId);
+ }
+
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ }
+
public bool Equals(FileIdentifier other) => _value == other._value;
public override bool Equals([NotNullWhen(true)] object? obj) => obj is FileIdentifier identifier && Equals(identifier);
public override int GetHashCode() => _value.GetHashCode();
diff --git a/src/Meziantou.Framework.Win32.ChangeJournal/Meziantou.Framework.Win32.ChangeJournal.csproj b/src/Meziantou.Framework.Win32.ChangeJournal/Meziantou.Framework.Win32.ChangeJournal.csproj
index a3945fec..c42bbc6e 100644
--- a/src/Meziantou.Framework.Win32.ChangeJournal/Meziantou.Framework.Win32.ChangeJournal.csproj
+++ b/src/Meziantou.Framework.Win32.ChangeJournal/Meziantou.Framework.Win32.ChangeJournal.csproj
@@ -4,7 +4,7 @@
$(LatestTargetFrameworks)
false
Meziantou.Framework.Win32
- 3.0.0
+ 3.1.0
Allow to access the Windows Change Journal to quickly detect changed files
diff --git a/src/Meziantou.Framework.Win32.ChangeJournal/NativeMethods.txt b/src/Meziantou.Framework.Win32.ChangeJournal/NativeMethods.txt
index 376efc23..509ada48 100644
--- a/src/Meziantou.Framework.Win32.ChangeJournal/NativeMethods.txt
+++ b/src/Meziantou.Framework.Win32.ChangeJournal/NativeMethods.txt
@@ -11,4 +11,6 @@ Windows.Win32.System.Ioctl.USN_RECORD_V2
Windows.Win32.System.Ioctl.USN_RECORD_V3
Windows.Win32.System.Ioctl.USN_RECORD_V4
Windows.Win32.System.Ioctl.USN_TRACK_MODIFIED_RANGES
-FLAG_USN_TRACK_MODIFIED_RANGES_ENABLE
\ No newline at end of file
+FLAG_USN_TRACK_MODIFIED_RANGES_ENABLE
+GetFileInformationByHandleEx
+FILE_ID_INFO
\ No newline at end of file
diff --git a/tests/Meziantou.Framework.Win32.ChangeJournal.Tests/ChangeJournalTests.cs b/tests/Meziantou.Framework.Win32.ChangeJournal.Tests/ChangeJournalTests.cs
index 4124e8e5..90d19449 100644
--- a/tests/Meziantou.Framework.Win32.ChangeJournal.Tests/ChangeJournalTests.cs
+++ b/tests/Meziantou.Framework.Win32.ChangeJournal.Tests/ChangeJournalTests.cs
@@ -75,6 +75,14 @@ public void NonAdministrator()
});
}
+ [RunIfFact(FactOperatingSystem.Windows)]
+ public void GetFileIdentifier()
+ {
+ var file = Path.GetTempFileName();
+ var identifier = FileIdentifier.FromFile(file);
+ Assert.NotEqual(default, identifier);
+ }
+
[Fact]
public void FileIdentifier128ToString()
{